nut-2.7.2/0000755000175000017500000000000012324034436007332 500000000000000nut-2.7.2/conf/0000755000175000017500000000000012324034434010255 500000000000000nut-2.7.2/conf/upsd.users.sample0000644000175000017500000000412312277355125013525 00000000000000# Network UPS Tools: Example upsd.users # # This file sets the permissions for upsd - the UPS network daemon. # Users are defined here, are given passwords, and their privileges are # controlled here too. Since this file will contain passwords, keep it # secure, with only enough permissions for upsd to read it. # -------------------------------------------------------------------------- # Each user gets a section. To start a section, put the username in # brackets on a line by itself. To set something for that user, specify # it under that section heading. The username is case-sensitive, so # admin and AdMiN are two different users. # # Possible settings: # # password: The user's password. This is case-sensitive. # # -------------------------------------------------------------------------- # # actions: Let the user do certain things with upsd. # # Valid actions are: # # SET - change the value of certain variables in the UPS # FSD - set the "forced shutdown" flag in the UPS # # -------------------------------------------------------------------------- # # instcmds: Let the user initiate specific instant commands. Use "ALL" # to grant all commands automatically. There are many possible # commands, so use 'upscmd -l' to see what your hardware supports. Here # are a few examples: # # test.panel.start - Start a front panel test # test.battery.start - Start battery test # test.battery.stop - Stop battery test # calibrate.start - Start calibration # calibrate.stop - Stop calibration # # -------------------------------------------------------------------------- # # Example: # # [admin] # password = mypass # actions = SET # instcmds = ALL # # # --- Configuring for a user who can execute tests only # # [testuser] # password = pass # instcmds = test.battery.start # instcmds = test.battery.stop # # --- Configuring for upsmon # # To add a user for your upsmon, use this example: # # [upsmon] # password = pass # upsmon master # or # upsmon slave # # The matching MONITOR line in your upsmon.conf would look like this: # # MONITOR myups@localhost 1 upsmon pass master (or slave) nut-2.7.2/conf/upsstats-single.html.sample0000644000175000017500000001476412277355125015536 00000000000000 @TEMPC@ @UPSSTATSPATH upsstats.cgi@ @UPSIMAGEPATH upsimage.cgi@ @REFRESH@ @HOSTDESC@ : @VAR ups.model@ on @HOST@ @IFSUPP ambient.temperature@ @ELSE@ @IFSUPP ambient.humidity@ @ENDIF@ @IFSUPP ambient.temperature@ @IFSUPP ambient.humidity@ @ELSE@ @IFSUPP ambient.temperature@ @ELSE@ @IFSUPP ambient.humidity@ @ENDIF@
Network UPS Tools upsstats @VERSION@ - @HOSTDESC@ - @VAR ups.model@ on @HOST@
@DATE %a %b %d %X %Z %Y@AmbientAmbientBattery Input Output Load
@IFSUPP battery.runtime@ @ENDIF@ @IFSUPP ups.temperature@ @ENDIF@ @IFSUPP battery.voltage@ @ENDIF@ @ELSE@ @IFSUPP input.L2-N.voltage@ @VAR input.L1-N.voltage@ V
@VAR input.L2-N.voltage@ V
@VAR input.L3-N.voltage@ V
@ELSE@ @IFSUPP input.voltage@ @VAR input.voltage@ V
@ENDIF@ @IFSUPP input.L2.current@ @ELSE@ @IFSUPP input.current@ @ENDIF@ @IFSUPP input.frequency@ @ENDIF@ @ELSE@ @IFSUPP output.L2-N.voltage@ @VAR output.L1-N.voltage@ V
@VAR output.L2-N.voltage@ V
@VAR output.L3-N.voltage@ V
@ELSE@ @IFSUPP output.voltage@ @VAR output.voltage@ V @ENDIF@ @IFSUPP output.L2.current@ @ELSE@ @IFSUPP output.current@ @ENDIF@ @IFSUPP output.frequency@ @ENDIF@
UPS Model: @VAR ups.model@
Status: @STATUS@
Runtime: @RUNTIME@
UPS temp: @UPSTEMP@ @DEGREES@
Battery: @VAR battery.voltage@ V@IFSUPP battery.current@, @VAR battery.current@ A
Input: @IFSUPP input.L2-L3.voltage@ @VAR input.L1-L2.voltage@ V
@VAR input.L2-L3.voltage@ V
@VAR input.L3-L1.voltage@ V
@VAR input.L1.current@ A
@VAR input.L2.current@ A
@VAR input.L3.current@ A
@VAR input.current@ A
@VAR input.frequency@ Hz
Output: @IFSUPP output.L2-L3.voltage@ @VAR output.L1-L2.voltage@ V
@VAR output.L2-L3.voltage@ V
@VAR output.L3-L1.voltage@ V
@VAR output.L1.current@ A
@VAR output.L2.current@ A
@VAR output.L3.current@ A
@VAR output.current@ A
@VAR output.frequency@ Hz
Temperature
@IMG ambient.temperature tempmin=0 tempmax=50 width=90@
Humidity
@IMG ambient.humidity width=90@
Temperature
@IMG ambient.temperature tempmin=0 tempmax=50@
Humidity
@IMG ambient.humidity@
@IFSUPP battery.charge@ @IFSUPP battery.voltage@ @ELSE@ @IFSUPP battery.charge@ @ELSE@ @ENDIF@
Charge
@IMG battery.charge width=90@
Voltage
@IMG battery.voltage width=90@
Charge
@IMG battery.charge@
Voltage
@IMG battery.voltage@
@IFSUPP input.L2-L3.voltage@ @ELSE@ @IFSUPP input.L2-N.voltage@ @ELSE@ @ENDIF@
L1-L2
@IMG input.L1-L2.voltage width=68@
L2-L3
@IMG input.L2-L3.voltage width=68@
L3-L1
@IMG input.L3-L1.voltage width=68@
L1-N
@IMG input.L1-N.voltage width=68@
L2-N
@IMG input.L2-N.voltage width=68@
L3-N
@IMG input.L3-N.voltage width=68@

@IMG input.voltage@
@IFSUPP output.L2-L3.voltage@ @ELSE@ @IFSUPP output.L2-N.voltage@ @ELSE@ @ENDIF@
L1-L2
@IMG output.L1-L2.voltage width=68@
L2-L3
@IMG output.L2-L3.voltage width=68@
L3-L1
@IMG output.L3-L1.voltage width=68@
L1-N
@IMG output.L1-N.voltage width=68@
L2-N
@IMG output.L2-N.voltage width=68@
L3-N
@IMG output.L3-N.voltage width=68@

@IMG output.voltage@
@IFSUPP output.L2.power.percent@ @ELSE@ @IFSUPP output.L2.realpower.percent@ @ELSE@ @ENDIF@
L1
@IMG output.L1.power.percent width=68@
L2
@IMG output.L2.power.percent width=68@
L3
@IMG output.L3.power.percent width=68@
L1
@IMG output.L1.realpower.percent width=68@
L2
@IMG output.L2.realpower.percent width=68@
L3
@IMG output.L3.realpower.percent width=68@

@IMG ups.load@
Valid HTML 4.0 Transitional nut-2.7.2/conf/upsset.conf.sample0000644000175000017500000000261412277355125013664 00000000000000# Network UPS Tools - upsset.conf sample file # # This file is provided to ensure that you do not expose your upsd server # to the world upon installing the CGI programs. Specifically, it keeps # the upsset.cgi program from running until you have assured it that you # have secured your web server's CGI directory. # # By default, your web server will probably let anyone access upsset.cgi # once it is installed. This means that anyone could attempt to crack # upsd logins since they would appear to be coming from your web server, # rather than the outside world, slipping through any ACL/ACCESS definitions. # # For this reason, you *MUST* first secure your CGI programs before # enabling upsset in this configuration file. If you can't do this in # your web server, then you should *not* run this program. # # For Apache, the .htaccess file can be used in the directory with the # programs. You'll need something like this: # # # deny from all # allow from your.network.addresses # # # You will probably have to set "AllowOverride Limit" for this directory in # your server-level configuration file as well. # # If this doesn't make sense, then stop reading and leave this program alone. # # Assuming you have all this done (and it works), then you may uncomment # the line below and start using upsset.cgi through your web browser. # ### ### I_HAVE_SECURED_MY_CGI_DIRECTORY ### nut-2.7.2/conf/Makefile.am0000644000175000017500000000070712277355125012247 00000000000000# Network UPS Tools: conf INSTALL_0600 = $(INSTALL) -m 0600 SECFILES = upsmon.conf.sample upsd.conf.sample upsd.users.sample PUBFILES = nut.conf.sample ups.conf.sample CGIPUB = hosts.conf.sample upsset.conf.sample upsstats.html.sample \ upsstats-single.html.sample if WITH_CGI CGI_INSTALL = $(CGIPUB) else CGI_INSTALL = endif dist_sysconf_DATA = $(SECFILES) $(PUBFILES) $(CGI_INSTALL) nodist_sysconf_DATA = upssched.conf.sample upsmon.conf.sample nut-2.7.2/conf/upsmon.conf.sample0000644000175000017500000003552412324034430013652 00000000000000# Network UPS Tools: example upsmon configuration # # This file contains passwords, so keep it secure. # -------------------------------------------------------------------------- # RUN_AS_USER # # By default, upsmon splits into two processes. One stays as root and # waits to run the SHUTDOWNCMD. The other one switches to another userid # and does everything else. # # The default nonprivileged user is set at compile-time with # 'configure --with-user=...'. # # You can override it with '-u ' when starting upsmon, or just # define it here for convenience. # # Note: if you plan to use the reload feature, this file (upsmon.conf) # must be readable by this user! Since it contains passwords, DO NOT # make it world-readable. Also, do not make it writable by the upsmon # user, since it creates an opportunity for an attack by changing the # SHUTDOWNCMD to something malicious. # # For best results, you should create a new normal user like "nutmon", # and make it a member of a "nut" group or similar. Then specify it # here and grant read access to the upsmon.conf for that group. # # This user should not have write access to upsmon.conf. # # RUN_AS_USER nut # -------------------------------------------------------------------------- # MONITOR ("master"|"slave") # # List systems you want to monitor. Not all of these may supply power # to the system running upsmon, but if you want to watch it, it has to # be in this section. # # You must have at least one of these declared. # # is a UPS identifier in the form @[:] # like ups@localhost, su700@mybox, etc. # # Examples: # # - "su700@mybox" means a UPS called "su700" on a system called "mybox" # # - "fenton@bigbox:5678" is a UPS called "fenton" on a system called # "bigbox" which runs upsd on port "5678". # # The UPS names like "su700" and "fenton" are set in your ups.conf # in [brackets] which identify a section for a particular driver. # # If the ups.conf on host "doghouse" has a section called "snoopy", the # identifier for it would be "snoopy@doghouse". # # is an integer - the number of power supplies that this UPS # feeds on this system. Most computers only have one power supply, so this # is normally set to 1. You need a pretty big or special box to have any # other value here. # # You can also set this to 0 for a system that doesn't supply any power, # but you still want to monitor. Use this when you want to hear about # changes for a given UPS without shutting down when it goes critical, # unless is 0. # # and must match an entry in that system's # upsd.users. If your username is "monmaster" and your password is # "blah", the upsd.users would look like this: # # [monmaster] # password = blah # upsmon master (or slave) # # "master" means this system will shutdown last, allowing the slaves # time to shutdown first. # # "slave" means this system shuts down immediately when power goes critical. # # Examples: # # MONITOR myups@bigserver 1 monmaster blah master # MONITOR su700@server.example.com 1 upsmon secretpass slave # MONITOR myups@localhost 1 upsmon pass master (or slave) # -------------------------------------------------------------------------- # MINSUPPLIES # # Give the number of power supplies that must be receiving power to keep # this system running. Most systems have one power supply, so you would # put "1" in this field. # # Large/expensive server type systems usually have more, and can run with # a few missing. The HP NetServer LH4 can run with 2 out of 4, for example, # so you'd set that to 2. The idea is to keep the box running as long # as possible, right? # # Obviously you have to put the redundant supplies on different UPS circuits # for this to make sense! See big-servers.txt in the docs subdirectory # for more information and ideas on how to use this feature. MINSUPPLIES 1 # -------------------------------------------------------------------------- # SHUTDOWNCMD "" # # upsmon runs this command when the system needs to be brought down. # # This should work just about everywhere ... if it doesn't, well, change it. SHUTDOWNCMD "/sbin/shutdown -h +0" # -------------------------------------------------------------------------- # NOTIFYCMD # # upsmon calls this to send messages when things happen # # This command is called with the full text of the message as one argument. # The environment string NOTIFYTYPE will contain the type string of # whatever caused this event to happen. # # Note that this is only called for NOTIFY events that have EXEC set with # NOTIFYFLAG. See NOTIFYFLAG below for more details. # # Making this some sort of shell script might not be a bad idea. For more # information and ideas, see docs/scheduling.txt # # Example: # NOTIFYCMD /usr/local/ups/bin/notifyme # -------------------------------------------------------------------------- # POLLFREQ # # Polling frequency for normal activities, measured in seconds. # # Adjust this to keep upsmon from flooding your network, but don't make # it too high or it may miss certain short-lived power events. POLLFREQ 5 # -------------------------------------------------------------------------- # POLLFREQALERT # # Polling frequency in seconds while UPS on battery. # # You can make this number lower than POLLFREQ, which will make updates # faster when any UPS is running on battery. This is a good way to tune # network load if you have a lot of these things running. # # The default is 5 seconds for both this and POLLFREQ. POLLFREQALERT 5 # -------------------------------------------------------------------------- # HOSTSYNC - How long upsmon will wait before giving up on another upsmon # # The master upsmon process uses this number when waiting for slaves to # disconnect once it has set the forced shutdown (FSD) flag. If they # don't disconnect after this many seconds, it goes on without them. # # Similarly, upsmon slave processes wait up to this interval for the # master upsmon to set FSD when a UPS they are monitoring goes critical - # that is, on battery and low battery. If the master doesn't do its job, # the slaves will shut down anyway to avoid damage to the file systems. # # This "wait for FSD" is done to avoid races where the status changes # to critical and back between polls by the master. HOSTSYNC 15 # -------------------------------------------------------------------------- # DEADTIME - Interval to wait before declaring a stale ups "dead" # # upsmon requires a UPS to provide status information every few seconds # (see POLLFREQ and POLLFREQALERT) to keep things updated. If the status # fetch fails, the UPS is marked stale. If it stays stale for more than # DEADTIME seconds, the UPS is marked dead. # # A dead UPS that was last known to be on battery is assumed to have gone # to a low battery condition. This may force a shutdown if it is providing # a critical amount of power to your system. # # Note: DEADTIME should be a multiple of POLLFREQ and POLLFREQALERT. # Otherwise you'll have "dead" UPSes simply because upsmon isn't polling # them quickly enough. Rule of thumb: take the larger of the two # POLLFREQ values, and multiply by 3. DEADTIME 15 # -------------------------------------------------------------------------- # POWERDOWNFLAG - Flag file for forcing UPS shutdown on the master system # # upsmon will create a file with this name in master mode when it's time # to shut down the load. You should check for this file's existence in # your shutdown scripts and run 'upsdrvctl shutdown' if it exists. # # See the shutdown.txt file in the docs subdirectory for more information. POWERDOWNFLAG /etc/nut/killpower # -------------------------------------------------------------------------- # NOTIFYMSG - change messages sent by upsmon when certain events occur # # You can change the default messages to something else if you like. # # NOTIFYMSG "message" # # NOTIFYMSG ONLINE "UPS %s on line power" # NOTIFYMSG ONBATT "UPS %s on battery" # NOTIFYMSG LOWBATT "UPS %s battery is low" # NOTIFYMSG FSD "UPS %s: forced shutdown in progress" # NOTIFYMSG COMMOK "Communications with UPS %s established" # NOTIFYMSG COMMBAD "Communications with UPS %s lost" # NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding" # NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced" # NOTIFYMSG NOCOMM "UPS %s is unavailable" # NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible" # # Note that %s is replaced with the identifier of the UPS in question. # # Possible values for : # # ONLINE : UPS is back online # ONBATT : UPS is on battery # LOWBATT : UPS has a low battery (if also on battery, it's "critical") # FSD : UPS is being shutdown by the master (FSD = "Forced Shutdown") # COMMOK : Communications established with the UPS # COMMBAD : Communications lost to the UPS # SHUTDOWN : The system is being shutdown # REPLBATT : The UPS battery is bad and needs to be replaced # NOCOMM : A UPS is unavailable (can't be contacted for monitoring) # NOPARENT : The process that shuts down the system has died (shutdown impossible) # -------------------------------------------------------------------------- # NOTIFYFLAG - change behavior of upsmon when NOTIFY events occur # # By default, upsmon sends walls (global messages to all logged in users) # and writes to the syslog when things happen. You can change this. # # NOTIFYFLAG [+][+] ... # # NOTIFYFLAG ONLINE SYSLOG+WALL # NOTIFYFLAG ONBATT SYSLOG+WALL # NOTIFYFLAG LOWBATT SYSLOG+WALL # NOTIFYFLAG FSD SYSLOG+WALL # NOTIFYFLAG COMMOK SYSLOG+WALL # NOTIFYFLAG COMMBAD SYSLOG+WALL # NOTIFYFLAG SHUTDOWN SYSLOG+WALL # NOTIFYFLAG REPLBATT SYSLOG+WALL # NOTIFYFLAG NOCOMM SYSLOG+WALL # NOTIFYFLAG NOPARENT SYSLOG+WALL # # Possible values for the flags: # # SYSLOG - Write the message in the syslog # WALL - Write the message to all users on the system # EXEC - Execute NOTIFYCMD (see above) with the message # IGNORE - Don't do anything # # If you use IGNORE, don't use any other flags on the same line. # -------------------------------------------------------------------------- # RBWARNTIME - replace battery warning time in seconds # # upsmon will normally warn you about a battery that needs to be replaced # every 43200 seconds, which is 12 hours. It does this by triggering a # NOTIFY_REPLBATT which is then handled by the usual notify structure # you've defined above. # # If this number is not to your liking, override it here. RBWARNTIME 43200 # -------------------------------------------------------------------------- # NOCOMMWARNTIME - no communications warning time in seconds # # upsmon will let you know through the usual notify system if it can't # talk to any of the UPS entries that are defined in this file. It will # trigger a NOTIFY_NOCOMM by default every 300 seconds unless you # change the interval with this directive. NOCOMMWARNTIME 300 # -------------------------------------------------------------------------- # FINALDELAY - last sleep interval before shutting down the system # # On a master, upsmon will wait this long after sending the NOTIFY_SHUTDOWN # before executing your SHUTDOWNCMD. If you need to do something in between # those events, increase this number. Remember, at this point your UPS is # almost depleted, so don't make this too high. # # Alternatively, you can set this very low so you don't wait around when # it's time to shut down. Some UPSes don't give much warning for low # battery and will require a value of 0 here for a safe shutdown. # # Note: If FINALDELAY on the slave is greater than HOSTSYNC on the master, # the master will give up waiting for the slave to disconnect. FINALDELAY 5 # -------------------------------------------------------------------------- # CERTPATH - path to certificates (database directory or directory with CA's) # # When compiled with SSL support, you can enter the certificate path here. # # With NSS: # Certificates are stored in a dedicated database (splitted in 3 files). # Specify the path of the database directory. # # CERTPATH /etc/nut/cert/upsmon # # With OpenSSL: # Directory containing CA certificates in PEM format, used to verify # the server certificate presented by the upsd server. The files each # contain one CA certificate. The files are looked up by the CA subject # name hash value, which must hence be available. # # CERTPATH /usr/ssl/certs # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # -------------------------------------------------------------------------- # CERTIDENT - self certificate name and database password # CERTIDENT # # When compiled with SSL support with NSS, you can specify the certificate # name to retrieve from database to authenticate itself and the password # required to access certificate related private key. # # CERTIDENT "my nut monitor" "MyPasSw0rD" # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # -------------------------------------------------------------------------- # CERTHOST - security properties for an host # CERTHOST # # When compiled with SSL support with NSS, you can specify security directive # for each server you can contact. # Each entry maps server name with the expected certificate name and flags # indicating if the server certificate is verified and if the connection # must be secure. # # CERTHOST localhost "My nut server" 1 1 # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # -------------------------------------------------------------------------- # CERTVERIFY - make upsmon verify all connections with certificates # CERTVERIFY 1 # # When compiled with SSL support, make upsmon verify all connections with # certificates. # Without this, there is no guarantee that the upsd is the right host. # Enabling this greatly reduces the risk of man in the middle attacks. # This effectively forces the use of SSL, so don't use this unless # all of your upsd hosts are ready for SSL and have their certificates # in order. # When compiled with NSS support of SSL, can be overriden for host # specified with a CERTHOST directive. # -------------------------------------------------------------------------- # FORCESSL - force upsmon to use SSL # FORCESSL 1 # # When compiled with SSL, specify that a secured connection must be used # to communicate with upsd. # If you don't use 'CERTVERIFY 1', then this will at least make sure # that nobody can sniff your sessions without a large effort. Setting # this will make upsmon drop connections if the remote upsd doesn't # support SSL, so don't use it unless all of them have it running. # When compiled with NSS support of SSL, can be overriden for host # specified with a CERTHOST directive. nut-2.7.2/conf/hosts.conf.sample0000644000175000017500000000206012277355125013474 00000000000000# Network UPS Tools: example hosts.conf # # This file is used to control the CGI programs. If you have not # installed them, you may safely ignore or delete this file. # # ----------------------------------------------------------------------- # # upsstats will use the list of MONITOR entries when displaying the # default template (upsstats.html). The "FOREACHUPS" directive in the # template will use this file to find systems running upsd. # # upsstats and upsimage also use this file to determine if a host may be # monitored. This keeps evil people from using your system to annoy # others with unintended queries. # # upsset presents a list of systems that may be viewed and controlled # using this file. # # ----------------------------------------------------------------------- # # Usage: list systems running upsd that you want to monitor # # MONITOR "" # # Examples: # # MONITOR myups@localhost "Local UPS" # MONITOR su2200@10.64.1.1 "Finance department" # MONITOR matrix@shs-server.example.edu "Sierra High School data room #1" nut-2.7.2/conf/upssched.conf.sample.in0000644000175000017500000000746112277355125014571 00000000000000# Network UPS Tools - upssched.conf sample file # # ============================================================================ # # CMDSCRIPT # # This script gets called to invoke commands for timers that trigger. # It is given a single argument - the in your # AT ... START-TIMER defines. # # *** This must be defined *before* the first AT line. Otherwise the # program will complain and exit without doing anything. # # A shell script with a big case..esac construct should work nicely for this. # An example has been provided to help you get started. CMDSCRIPT @BINDIR@/upssched-cmd # ============================================================================ # # PIPEFN # # This sets the file name of the FIFO that will pass communications between # processes to start and stop timers. This should be set to some path where # normal users can't create the file, due to the possibility of symlinking # and other evil. # # Note: if you are running Solaris or similar, the permissions that # upssched sets on this file *are not enough* to keep you safe. If # your OS ignores the permissions on a FIFO, then you MUST put this in # a protected directory! # # Note 2: by default, upsmon will run upssched as whatever user you have # defined with RUN_AS_USER in upsmon.conf. Make sure that user can # create files and write to files in the path you use for PIPEFN and # LOCKFN. # # My recommendation: create a special directory for upssched, make it # owned by your upsmon user, then use it for both. # # This is commented out by default to make you visit this file and think # about how your system works before potentially opening a hole. # # PIPEFN @STATEPATH@/upssched/upssched.pipe # ============================================================================ # # LOCKFN # # REQUIRED. This was added after version 1.2.1. # # upssched needs to be able to create this filename in order to avoid # a race condition when two events are dispatched from upsmon at nearly # the same time. This file will only exist briefly. It must not be # created by any other process. # # You should put this in the same directory as PIPEFN. # # LOCKFN @STATEPATH@/upssched/upssched.lock # ============================================================================ # # AT # # Define a handler for a specific event on UPS . # # can be the special value * to apply this handler to every # possible value of . # # Run the command via your CMDSCRIPT when it happens. # # Note that any AT that matches both the and the # for the current event will be used. # ============================================================================ # # Possible AT commands # # - START-TIMER # # Start a timer called that will trigger after # seconds, calling your CMDSCRIPT with as the first # argument. # # Example: # Start a timer that'll execute when any UPS (*) has been gone 10 seconds # # AT COMMBAD * START-TIMER upsgone 10 # ----------------------------------------------------------------------- # # - CANCEL-TIMER [cmd] # # Cancel a running timer called , if possible. If the timer # has passed then pass the optional argument to CMDSCRIPT. # # Example: # If a specific UPS (myups@localhost) comes back online, then stop the # timer before it triggers # # AT COMMOK myups@localhost CANCEL-TIMER upsgone # ----------------------------------------------------------------------- # # - EXECUTE # # Immediately pass as an argument to CMDSCRIPT. # # Example: # If any UPS (*) reverts to utility power, then execute # 'ups-back-on-line' via CMDSCRIPT. # # AT ONLINE * EXECUTE ups-back-on-line nut-2.7.2/conf/ups.conf.sample0000644000175000017500000000712412277355125013151 00000000000000# Network UPS Tools: example ups.conf # # --- SECURITY NOTE --- # # If you use snmp-ups and set a community string in here, you # will have to secure this file to keep other users from obtaining # that string. It needs to be readable by upsdrvctl and any drivers, # and by upsd. # # --- # # This is where you configure all the UPSes that this system will be # monitoring directly. These are usually attached to serial ports, but # USB devices and SNMP devices are also supported. # # This file is used by upsdrvctl to start and stop your driver(s), and # is also used by upsd to determine which drivers to monitor. The # drivers themselves also read this file for configuration directives. # # The general form is: # # [upsname] # driver = # port = # < any other directives here > # # The section header ([upsname]) can be just about anything as long as # it is a single word inside brackets. upsd uses this to uniquely # identify a UPS on this system. # # If you have a UPS called snoopy, your section header would be "[snoopy]". # On a system called "doghouse", the line in your upsmon.conf to monitor # it would look something like this: # # MONITOR snoopy@doghouse 1 upsmonuser mypassword master # # It might look like this if monitoring in slave mode: # # MONITOR snoopy@doghouse 1 upsmonuser mypassword slave # # Configuration directives # ------------------------ # # These directives are common to all drivers that support ups.conf: # # driver: REQUIRED. Specify the program to run to talk to this UPS. # apcsmart, bestups, and sec are some examples. # # port: REQUIRED. The serial port where your UPS is connected. # /dev/ttyS0 is usually the first port on Linux boxes, for example. # # sdorder: optional. When you have multiple UPSes on your system, you # usually need to turn them off in a certain order. upsdrvctl # shuts down all the 0s, then the 1s, 2s, and so on. To exclude # a UPS from the shutdown sequence, set this to -1. # # The default value for this parameter is 0. # # nolock: optional, and not recommended for use in this file. # # If you put nolock in here, the driver will not lock the # serial port every time it starts. This may allow other # processes to seize the port if you start more than one by # mistake. # # This is only intended to be used on systems where locking # absolutely must be disabled for the software to work. # # maxstartdelay: optional. This can be set as a global variable # above your first UPS definition and it can also be # set in a UPS section. This value controls how long # upsdrvctl will wait for the driver to finish starting. # This keeps your system from getting stuck due to a # broken driver or UPS. # # The default is 45 seconds. # # # Anything else is passed through to the hardware-specific part of # the driver. # # Examples # -------- # # A simple example for a UPS called "powerpal" that uses the blazer_ser # driver on /dev/ttyS0 is: # # [powerpal] # driver = blazer_ser # port = /dev/ttyS0 # desc = "Web server" # # If your UPS driver requires additional settings, you can specify them # here. For example, if it supports a setting of "1234" for the # variable "cable", it would look like this: # # [myups] # driver = mydriver # port = /dev/ttyS1 # cable = 1234 # desc = "Something descriptive" # # To find out if your driver supports any extra settings, start it with # the -h option and/or read the driver's documentation. nut-2.7.2/conf/Makefile.in0000644000175000017500000004173112324034367012255 00000000000000# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Network UPS Tools: conf VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = conf DIST_COMMON = $(am__dist_sysconf_DATA_DIST) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/upsmon.conf.sample.in \ $(srcdir)/upssched.conf.sample.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nut_arg_with.m4 \ $(top_srcdir)/m4/nut_check_asciidoc.m4 \ $(top_srcdir)/m4/nut_check_libavahi.m4 \ $(top_srcdir)/m4/nut_check_libfreeipmi.m4 \ $(top_srcdir)/m4/nut_check_libgd.m4 \ $(top_srcdir)/m4/nut_check_libltdl.m4 \ $(top_srcdir)/m4/nut_check_libneon.m4 \ $(top_srcdir)/m4/nut_check_libnetsnmp.m4 \ $(top_srcdir)/m4/nut_check_libnss.m4 \ $(top_srcdir)/m4/nut_check_libopenssl.m4 \ $(top_srcdir)/m4/nut_check_libpowerman.m4 \ $(top_srcdir)/m4/nut_check_libusb.m4 \ $(top_srcdir)/m4/nut_check_libwrap.m4 \ $(top_srcdir)/m4/nut_check_os.m4 \ $(top_srcdir)/m4/nut_report_feature.m4 \ $(top_srcdir)/m4/nut_type_socklen_t.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = upsmon.conf.sample upssched.conf.sample CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__dist_sysconf_DATA_DIST = upsmon.conf.sample upsd.conf.sample \ upsd.users.sample nut.conf.sample ups.conf.sample \ hosts.conf.sample upsset.conf.sample upsstats.html.sample \ upsstats-single.html.sample am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(sysconfdir)" DATA = $(dist_sysconf_DATA) $(nodist_sysconf_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) A2X = @A2X@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ ASCIIDOC = @ASCIIDOC@ ASPELL = @ASPELL@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONFPATH = @CONFPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBLATEX = @DBLATEX@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOC_BUILD_LIST = @DOC_BUILD_LIST@ DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@ DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@ DRIVER_MAN_LIST = @DRIVER_MAN_LIST@ DRVPATH = @DRVPATH@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAVAHI_CFLAGS = @LIBAVAHI_CFLAGS@ LIBAVAHI_LIBS = @LIBAVAHI_LIBS@ LIBGD_CFLAGS = @LIBGD_CFLAGS@ LIBGD_LDFLAGS = @LIBGD_LDFLAGS@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@ LIBIPMI_LIBS = @LIBIPMI_LIBS@ LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@ LIBLTDL_LIBS = @LIBLTDL_LIBS@ LIBNEON_CFLAGS = @LIBNEON_CFLAGS@ LIBNEON_LIBS = @LIBNEON_LIBS@ LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@ LIBNETSNMP_LIBS = @LIBNETSNMP_LIBS@ LIBOBJS = @LIBOBJS@ LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@ LIBS = @LIBS@ LIBSSL_CFLAGS = @LIBSSL_CFLAGS@ LIBSSL_LIBS = @LIBSSL_LIBS@ LIBTOOL = @LIBTOOL@ LIBUSB_CFLAGS = @LIBUSB_CFLAGS@ LIBUSB_LIBS = @LIBUSB_LIBS@ LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@ LIBWRAP_LIBS = @LIBWRAP_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NETLIBS = @NETLIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NUT_NETVERSION = @NUT_NETVERSION@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_NAME = @OS_NAME@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIDPATH = @PIDPATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PORT = @PORT@ RANLIB = @RANLIB@ RUN_AS_GROUP = @RUN_AS_GROUP@ RUN_AS_USER = @RUN_AS_USER@ SBINDIR = @SBINDIR@ SED = @SED@ SERLIBS = @SERLIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STATEPATH = @STATEPATH@ STRIP = @STRIP@ SUN_LIBUSB = @SUN_LIBUSB@ TREE_VERSION = @TREE_VERSION@ VERSION = @VERSION@ WORDS_BIGENDIAN = @WORDS_BIGENDIAN@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ cgiexecdir = @cgiexecdir@ datadir = @datadir@ datarootdir = @datarootdir@ devddir = @devddir@ docdir = @docdir@ driverexecdir = @driverexecdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ hotplugdir = @hotplugdir@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemdsystemshutdowndir = @systemdsystemshutdowndir@ systemdsystemunitdir = @systemdsystemunitdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udevdir = @udevdir@ INSTALL_0600 = $(INSTALL) -m 0600 SECFILES = upsmon.conf.sample upsd.conf.sample upsd.users.sample PUBFILES = nut.conf.sample ups.conf.sample CGIPUB = hosts.conf.sample upsset.conf.sample upsstats.html.sample \ upsstats-single.html.sample @WITH_CGI_FALSE@CGI_INSTALL = @WITH_CGI_TRUE@CGI_INSTALL = $(CGIPUB) dist_sysconf_DATA = $(SECFILES) $(PUBFILES) $(CGI_INSTALL) nodist_sysconf_DATA = upssched.conf.sample upsmon.conf.sample all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu conf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu conf/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): upsmon.conf.sample: $(top_builddir)/config.status $(srcdir)/upsmon.conf.sample.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ upssched.conf.sample: $(top_builddir)/config.status $(srcdir)/upssched.conf.sample.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_sysconfDATA: $(dist_sysconf_DATA) @$(NORMAL_INSTALL) @list='$(dist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sysconfdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \ done uninstall-dist_sysconfDATA: @$(NORMAL_UNINSTALL) @list='$(dist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(sysconfdir)'; $(am__uninstall_files_from_dir) install-nodist_sysconfDATA: $(nodist_sysconf_DATA) @$(NORMAL_INSTALL) @list='$(nodist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sysconfdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \ done uninstall-nodist_sysconfDATA: @$(NORMAL_UNINSTALL) @list='$(nodist_sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(sysconfdir)'; $(am__uninstall_files_from_dir) tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(sysconfdir)" "$(DESTDIR)$(sysconfdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-dist_sysconfDATA install-nodist_sysconfDATA install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_sysconfDATA uninstall-nodist_sysconfDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dist_sysconfDATA \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-nodist_sysconfDATA install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-dist_sysconfDATA uninstall-nodist_sysconfDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: nut-2.7.2/conf/upsmon.conf.sample.in0000644000175000017500000003553012303134465014262 00000000000000# Network UPS Tools: example upsmon configuration # # This file contains passwords, so keep it secure. # -------------------------------------------------------------------------- # RUN_AS_USER # # By default, upsmon splits into two processes. One stays as root and # waits to run the SHUTDOWNCMD. The other one switches to another userid # and does everything else. # # The default nonprivileged user is set at compile-time with # 'configure --with-user=...'. # # You can override it with '-u ' when starting upsmon, or just # define it here for convenience. # # Note: if you plan to use the reload feature, this file (upsmon.conf) # must be readable by this user! Since it contains passwords, DO NOT # make it world-readable. Also, do not make it writable by the upsmon # user, since it creates an opportunity for an attack by changing the # SHUTDOWNCMD to something malicious. # # For best results, you should create a new normal user like "nutmon", # and make it a member of a "nut" group or similar. Then specify it # here and grant read access to the upsmon.conf for that group. # # This user should not have write access to upsmon.conf. # # RUN_AS_USER @RUN_AS_USER@ # -------------------------------------------------------------------------- # MONITOR ("master"|"slave") # # List systems you want to monitor. Not all of these may supply power # to the system running upsmon, but if you want to watch it, it has to # be in this section. # # You must have at least one of these declared. # # is a UPS identifier in the form @[:] # like ups@localhost, su700@mybox, etc. # # Examples: # # - "su700@mybox" means a UPS called "su700" on a system called "mybox" # # - "fenton@bigbox:5678" is a UPS called "fenton" on a system called # "bigbox" which runs upsd on port "5678". # # The UPS names like "su700" and "fenton" are set in your ups.conf # in [brackets] which identify a section for a particular driver. # # If the ups.conf on host "doghouse" has a section called "snoopy", the # identifier for it would be "snoopy@doghouse". # # is an integer - the number of power supplies that this UPS # feeds on this system. Most computers only have one power supply, so this # is normally set to 1. You need a pretty big or special box to have any # other value here. # # You can also set this to 0 for a system that doesn't supply any power, # but you still want to monitor. Use this when you want to hear about # changes for a given UPS without shutting down when it goes critical, # unless is 0. # # and must match an entry in that system's # upsd.users. If your username is "monmaster" and your password is # "blah", the upsd.users would look like this: # # [monmaster] # password = blah # upsmon master (or slave) # # "master" means this system will shutdown last, allowing the slaves # time to shutdown first. # # "slave" means this system shuts down immediately when power goes critical. # # Examples: # # MONITOR myups@bigserver 1 monmaster blah master # MONITOR su700@server.example.com 1 upsmon secretpass slave # MONITOR myups@localhost 1 upsmon pass master (or slave) # -------------------------------------------------------------------------- # MINSUPPLIES # # Give the number of power supplies that must be receiving power to keep # this system running. Most systems have one power supply, so you would # put "1" in this field. # # Large/expensive server type systems usually have more, and can run with # a few missing. The HP NetServer LH4 can run with 2 out of 4, for example, # so you'd set that to 2. The idea is to keep the box running as long # as possible, right? # # Obviously you have to put the redundant supplies on different UPS circuits # for this to make sense! See big-servers.txt in the docs subdirectory # for more information and ideas on how to use this feature. MINSUPPLIES 1 # -------------------------------------------------------------------------- # SHUTDOWNCMD "" # # upsmon runs this command when the system needs to be brought down. # # This should work just about everywhere ... if it doesn't, well, change it. SHUTDOWNCMD "/sbin/shutdown -h +0" # -------------------------------------------------------------------------- # NOTIFYCMD # # upsmon calls this to send messages when things happen # # This command is called with the full text of the message as one argument. # The environment string NOTIFYTYPE will contain the type string of # whatever caused this event to happen. # # Note that this is only called for NOTIFY events that have EXEC set with # NOTIFYFLAG. See NOTIFYFLAG below for more details. # # Making this some sort of shell script might not be a bad idea. For more # information and ideas, see docs/scheduling.txt # # Example: # NOTIFYCMD @BINDIR@/notifyme # -------------------------------------------------------------------------- # POLLFREQ # # Polling frequency for normal activities, measured in seconds. # # Adjust this to keep upsmon from flooding your network, but don't make # it too high or it may miss certain short-lived power events. POLLFREQ 5 # -------------------------------------------------------------------------- # POLLFREQALERT # # Polling frequency in seconds while UPS on battery. # # You can make this number lower than POLLFREQ, which will make updates # faster when any UPS is running on battery. This is a good way to tune # network load if you have a lot of these things running. # # The default is 5 seconds for both this and POLLFREQ. POLLFREQALERT 5 # -------------------------------------------------------------------------- # HOSTSYNC - How long upsmon will wait before giving up on another upsmon # # The master upsmon process uses this number when waiting for slaves to # disconnect once it has set the forced shutdown (FSD) flag. If they # don't disconnect after this many seconds, it goes on without them. # # Similarly, upsmon slave processes wait up to this interval for the # master upsmon to set FSD when a UPS they are monitoring goes critical - # that is, on battery and low battery. If the master doesn't do its job, # the slaves will shut down anyway to avoid damage to the file systems. # # This "wait for FSD" is done to avoid races where the status changes # to critical and back between polls by the master. HOSTSYNC 15 # -------------------------------------------------------------------------- # DEADTIME - Interval to wait before declaring a stale ups "dead" # # upsmon requires a UPS to provide status information every few seconds # (see POLLFREQ and POLLFREQALERT) to keep things updated. If the status # fetch fails, the UPS is marked stale. If it stays stale for more than # DEADTIME seconds, the UPS is marked dead. # # A dead UPS that was last known to be on battery is assumed to have gone # to a low battery condition. This may force a shutdown if it is providing # a critical amount of power to your system. # # Note: DEADTIME should be a multiple of POLLFREQ and POLLFREQALERT. # Otherwise you'll have "dead" UPSes simply because upsmon isn't polling # them quickly enough. Rule of thumb: take the larger of the two # POLLFREQ values, and multiply by 3. DEADTIME 15 # -------------------------------------------------------------------------- # POWERDOWNFLAG - Flag file for forcing UPS shutdown on the master system # # upsmon will create a file with this name in master mode when it's time # to shut down the load. You should check for this file's existence in # your shutdown scripts and run 'upsdrvctl shutdown' if it exists. # # See the shutdown.txt file in the docs subdirectory for more information. POWERDOWNFLAG @CONFPATH@/killpower # -------------------------------------------------------------------------- # NOTIFYMSG - change messages sent by upsmon when certain events occur # # You can change the default messages to something else if you like. # # NOTIFYMSG "message" # # NOTIFYMSG ONLINE "UPS %s on line power" # NOTIFYMSG ONBATT "UPS %s on battery" # NOTIFYMSG LOWBATT "UPS %s battery is low" # NOTIFYMSG FSD "UPS %s: forced shutdown in progress" # NOTIFYMSG COMMOK "Communications with UPS %s established" # NOTIFYMSG COMMBAD "Communications with UPS %s lost" # NOTIFYMSG SHUTDOWN "Auto logout and shutdown proceeding" # NOTIFYMSG REPLBATT "UPS %s battery needs to be replaced" # NOTIFYMSG NOCOMM "UPS %s is unavailable" # NOTIFYMSG NOPARENT "upsmon parent process died - shutdown impossible" # # Note that %s is replaced with the identifier of the UPS in question. # # Possible values for : # # ONLINE : UPS is back online # ONBATT : UPS is on battery # LOWBATT : UPS has a low battery (if also on battery, it's "critical") # FSD : UPS is being shutdown by the master (FSD = "Forced Shutdown") # COMMOK : Communications established with the UPS # COMMBAD : Communications lost to the UPS # SHUTDOWN : The system is being shutdown # REPLBATT : The UPS battery is bad and needs to be replaced # NOCOMM : A UPS is unavailable (can't be contacted for monitoring) # NOPARENT : The process that shuts down the system has died (shutdown impossible) # -------------------------------------------------------------------------- # NOTIFYFLAG - change behavior of upsmon when NOTIFY events occur # # By default, upsmon sends walls (global messages to all logged in users) # and writes to the syslog when things happen. You can change this. # # NOTIFYFLAG [+][+] ... # # NOTIFYFLAG ONLINE SYSLOG+WALL # NOTIFYFLAG ONBATT SYSLOG+WALL # NOTIFYFLAG LOWBATT SYSLOG+WALL # NOTIFYFLAG FSD SYSLOG+WALL # NOTIFYFLAG COMMOK SYSLOG+WALL # NOTIFYFLAG COMMBAD SYSLOG+WALL # NOTIFYFLAG SHUTDOWN SYSLOG+WALL # NOTIFYFLAG REPLBATT SYSLOG+WALL # NOTIFYFLAG NOCOMM SYSLOG+WALL # NOTIFYFLAG NOPARENT SYSLOG+WALL # # Possible values for the flags: # # SYSLOG - Write the message in the syslog # WALL - Write the message to all users on the system # EXEC - Execute NOTIFYCMD (see above) with the message # IGNORE - Don't do anything # # If you use IGNORE, don't use any other flags on the same line. # -------------------------------------------------------------------------- # RBWARNTIME - replace battery warning time in seconds # # upsmon will normally warn you about a battery that needs to be replaced # every 43200 seconds, which is 12 hours. It does this by triggering a # NOTIFY_REPLBATT which is then handled by the usual notify structure # you've defined above. # # If this number is not to your liking, override it here. RBWARNTIME 43200 # -------------------------------------------------------------------------- # NOCOMMWARNTIME - no communications warning time in seconds # # upsmon will let you know through the usual notify system if it can't # talk to any of the UPS entries that are defined in this file. It will # trigger a NOTIFY_NOCOMM by default every 300 seconds unless you # change the interval with this directive. NOCOMMWARNTIME 300 # -------------------------------------------------------------------------- # FINALDELAY - last sleep interval before shutting down the system # # On a master, upsmon will wait this long after sending the NOTIFY_SHUTDOWN # before executing your SHUTDOWNCMD. If you need to do something in between # those events, increase this number. Remember, at this point your UPS is # almost depleted, so don't make this too high. # # Alternatively, you can set this very low so you don't wait around when # it's time to shut down. Some UPSes don't give much warning for low # battery and will require a value of 0 here for a safe shutdown. # # Note: If FINALDELAY on the slave is greater than HOSTSYNC on the master, # the master will give up waiting for the slave to disconnect. FINALDELAY 5 # -------------------------------------------------------------------------- # CERTPATH - path to certificates (database directory or directory with CA's) # # When compiled with SSL support, you can enter the certificate path here. # # With NSS: # Certificates are stored in a dedicated database (splitted in 3 files). # Specify the path of the database directory. # # CERTPATH @CONFPATH@/cert/upsmon # # With OpenSSL: # Directory containing CA certificates in PEM format, used to verify # the server certificate presented by the upsd server. The files each # contain one CA certificate. The files are looked up by the CA subject # name hash value, which must hence be available. # # CERTPATH /usr/ssl/certs # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # -------------------------------------------------------------------------- # CERTIDENT - self certificate name and database password # CERTIDENT # # When compiled with SSL support with NSS, you can specify the certificate # name to retrieve from database to authenticate itself and the password # required to access certificate related private key. # # CERTIDENT "my nut monitor" "MyPasSw0rD" # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # -------------------------------------------------------------------------- # CERTHOST - security properties for an host # CERTHOST # # When compiled with SSL support with NSS, you can specify security directive # for each server you can contact. # Each entry maps server name with the expected certificate name and flags # indicating if the server certificate is verified and if the connection # must be secure. # # CERTHOST localhost "My nut server" 1 1 # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # -------------------------------------------------------------------------- # CERTVERIFY - make upsmon verify all connections with certificates # CERTVERIFY 1 # # When compiled with SSL support, make upsmon verify all connections with # certificates. # Without this, there is no guarantee that the upsd is the right host. # Enabling this greatly reduces the risk of man in the middle attacks. # This effectively forces the use of SSL, so don't use this unless # all of your upsd hosts are ready for SSL and have their certificates # in order. # When compiled with NSS support of SSL, can be overriden for host # specified with a CERTHOST directive. # -------------------------------------------------------------------------- # FORCESSL - force upsmon to use SSL # FORCESSL 1 # # When compiled with SSL, specify that a secured connection must be used # to communicate with upsd. # If you don't use 'CERTVERIFY 1', then this will at least make sure # that nobody can sniff your sessions without a large effort. Setting # this will make upsmon drop connections if the remote upsd doesn't # support SSL, so don't use it unless all of them have it running. # When compiled with NSS support of SSL, can be overriden for host # specified with a CERTHOST directive. nut-2.7.2/conf/nut.conf.sample0000644000175000017500000000300212277355125013137 00000000000000# Network UPS Tools: example nut.conf # ############################################################################## # General section ############################################################################## # The MODE determines which part of the NUT is to be started, and which # configuration files must be modified. # # This file try to standardize the various files being found in the field, like # /etc/default/nut on Debian based systems, /etc/sysconfig/ups on RedHat based # systems, ... Distribution's init script should source this file to see which # component(s) has to be started. # # The values of MODE can be: # - none: NUT is not configured, or use the Integrated Power Management, or use # some external system to startup NUT components. So nothing is to be started. # - standalone: This mode address a local only configuration, with 1 UPS # protecting the local system. This implies to start the 3 NUT layers (driver, # upsd and upsmon) and the matching configuration files. This mode can also # address UPS redundancy. # - netserver: same as for the standalone configuration, but also need # some more network access controls (firewall, tcp-wrappers) and possibly a # specific LISTEN directive in upsd.conf. # Since this MODE is opened to the network, a special care should be applied # to security concerns. # - netclient: this mode only requires upsmon. # # IMPORTANT NOTE: # This file is intended to be sourced by shell scripts. # You MUST NOT use spaces around the equal sign! MODE=none nut-2.7.2/conf/upsstats.html.sample0000644000175000017500000000764312277355125014255 00000000000000 @TEMPC@ @UPSSTATSPATH upsstats.cgi@ @UPSIMAGEPATH upsimage.cgi@ @REFRESH@ Network UPS Tools upsstats @VERSION@ : UPS Status @REFRESH@
@FOREACHUPS@ @IFSUPP input.L2-L3.voltage@ @IFBETWEEN input.transfer.low input.transfer.high input.L1-L2.voltage@ @IFBETWEEN input.transfer.low input.transfer.high input.L2-L3.voltage@ @IFBETWEEN input.transfer.low input.transfer.high input.L3-L1.voltage@ @ENDFOR@
Network UPS Tools upsstats @VERSION@
@DATE %a %b %d %X %Z %Y@
System Model Status Battery Input (VAC) Output (VAC) Load (%) UPS
Temp
Battery
Runtime
Data
Tree
@HOSTLINK@ @VAR ups.model@ @STATUS@ @IFSUPP battery.charge@ @VAR battery.charge@ % @ENDIF@ @ELSE@ @IFSUPP input.L2-N.voltage@ @IFBETWEEN input.transfer.low input.transfer.high input.L1-N.voltage@ @IFBETWEEN input.transfer.low input.transfer.high input.L2-N.voltage@ @IFBETWEEN input.transfer.low input.transfer.high input.L3-N.voltage@ @ELSE@ @IFBETWEEN input.transfer.low input.transfer.high input.voltage@ @ELSE@ @ENDIF@ @IFSUPP input.L2-L3.voltage@ @VAR input.L1-L2.voltage@ @VAR input.L2-L3.voltage@ @VAR input.L3-L1.voltage@ @ELSE@ @IFSUPP input.L2-N.voltage@ @VAR input.L1-N.voltage@ @VAR input.L2-N.voltage@ @VAR input.L3-N.voltage@ @ELSE@ @IFSUPP input.voltage@ @VAR input.voltage@ @ENDIF@ @IFSUPP output.L2-L3.voltage@ @VAR output.L1-L2.voltage@ @VAR output.L2-L3.voltage@ @VAR output.L3-L1.voltage@ @ELSE@ @IFSUPP output.L2-N.voltage@ @VAR output.L1-N.voltage@ @VAR output.L2-N.voltage@ @VAR output.L3-N.voltage@ @ELSE@ @IFSUPP output.voltage@ @VAR output.voltage@ @ENDIF@ @IFSUPP output.L2.power.percent@ @VAR output.L1.power.percent@ @VAR output.L2.power.percent@ @VAR output.L3.power.percent@ @ELSE@ @IFSUPP output.L2.realpower.percent@ @VAR output.L1.realpower.percent@ @VAR output.L2.realpower.percent@ @VAR output.L3.realpower.percent@ @ELSE@ @IFSUPP ups.load@ @VAR ups.load@ % @ENDIF@ @IFSUPP ups.temperature@ @UPSTEMP@ @DEGREES@ @ELSE@ @IFSUPP battery.temperature@ @BATTTEMP@ @DEGREES@ @ENDIF@ @IFSUPP battery.runtime@ @RUNTIME@ @ENDIF@ @TREELINK@

Valid CSS! Valid HTML 4.0 Transitional
nut-2.7.2/conf/upsd.conf.sample0000644000175000017500000001074212301203176013277 00000000000000# Network UPS Tools: example upsd configuration file # # This file contains access control data, you should keep it secure. # # It should only be readable by the user that upsd becomes. See the FAQ. # # Each entry below provides usage and default value. # ======================================================================= # MAXAGE # MAXAGE 15 # # This defaults to 15 seconds. After a UPS driver has stopped updating # the data for this many seconds, upsd marks it stale and stops making # that information available to clients. After all, the only thing worse # than no data is bad data. # # You should only use this if your driver has difficulties keeping # the data fresh within the normal 15 second interval. Watch the syslog # for notifications from upsd about staleness. # ======================================================================= # STATEPATH # STATEPATH /var/run/nut # # Tell upsd to look for the driver state sockets in 'path' rather # than the default that was compiled into the program. # ======================================================================= # LISTEN
[] # LISTEN 127.0.0.1 3493 # LISTEN ::1 3493 # # This defaults to the localhost listening addresses and port 3493. # In case of IP v4 or v6 disabled kernel, only the available one will be used. # # You may specify each interface you want upsd to listen on for connections, # optionally with a port number. # # You may need this if you have multiple interfaces on your machine and # you don't want upsd to listen to all interfaces (for instance on a # firewall, you may not want to listen to the external interface). # # This will only be read at startup of upsd. If you make changes here, # you'll need to restart upsd, reload will have no effect. # ======================================================================= # MAXCONN # MAXCONN 1024 # # This defaults to maximum number allowed on your system. Each UPS, each # LISTEN address and each client count as one connection. If the server # runs out of connections, it will no longer accept new incoming client # connections. Only set this if you know exactly what you're doing. # ======================================================================= # CERTFILE # CERTFILE /usr/local/ups/etc/upsd.pem # # When compiled with SSL support with OpenSSL backend, # you can enter the certificate file here. # The certificates must be in PEM format and must be sorted starting with # the subject's certificate (server certificate), followed by intermediate # CA certificates (if applicable_ and the highest level (root) CA. It should # end with the server key. See 'docs/security.txt' or the Security chapter of # NUT user manual for more information on the SSL support in NUT. # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # ======================================================================= # CERTPATH # CERTPATH /usr/local/ups/etc/cert/upsd # # When compiled with SSL support with NSS backend, # you can enter the certificate path here. # Certificates are stored in a dedicated database (splitted in 3 files). # Specify the path of the database directory. # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # ======================================================================= # CERTIDENT # CERTIDENT "my nut server" "MyPasSw0rD" # # When compiled with SSL support with NSS backend, # you can specify the certificate name to retrieve from database to # authenticate itself and the password # required to access certificate related private key. # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. # ======================================================================= # CERTREQUEST # CERTREQUEST REQUIRE # # When compiled with SSL support with NSS backend and client certificate # validation (disabled by default, see 'docs/security.txt'), # you can specify if upsd requests or requires client's' certificates. # Possible values are : # - 0 to not request to clients to provide any certificate # - 1 to require to all clients a certificate # - 2 to require to all clients a valid certificate # # See 'docs/security.txt' or the Security chapter of NUT user manual # for more information on the SSL support in NUT. nut-2.7.2/tools/0000755000175000017500000000000012324034434010470 500000000000000nut-2.7.2/tools/nut-recorder.sh0000755000175000017500000000441112277355125013372 00000000000000#!/bin/sh ################################################################################ # # nut-recorder # An utility to record device running sequence (Ie power failures or any # other change) and dump it in a .seq format # The .seq file can then be used by the 'dummy-ups driver to replay the # sequence. # ################################################################################ # FIXME: # - implement PAUSE / RESUME (do not increment TIMER) on pressing space (?) # - implement support for creating either .dev (static dump) or .seq # - implement dump of instcmd and upsrw ################################################################################ strUsage="Usage: nut-recorder [output-file] [interval]" # log data each 5 seconds DEFAULT_INTERVAL=5 # temporary files location TEMP_DIR="/tmp" # output this file by default DEFAULT_OUTPUT="dummy-device.seq" # Process command line parameters if [ -z "$1" ]; then echo "$strUsage" exit else devName=$1 fi if [ -z "$2" ]; then outFile=$DEFAULT_OUTPUT else outFile=$2 fi if [ -z "$3" ]; then pollInterval=$DEFAULT_INTERVAL else pollInterval=$3 fi # initialize TIMER value curTimer=0 # Test communication with the device testResult="`upsc $devName > /dev/null`" if [ $? -gt 0 ]; then echo "$devName: $testResult" exit fi # initialize output file echo "# dummy-ups sequence recorded with $0\n"> $outFile # initialize data upsc $devName >> $outFile cp -f $outFile ${TEMP_DIR}/prevDump.tmp echo "Initial data:\n" cat $outFile while (true) do # rest a bit before getting fresh data sleep $pollInterval # update the TIMER value curTimer=`expr $curTimer + $pollInterval` # dump the current data testResult="`upsc $devName > ${TEMP_DIR}/curDump.tmp`" if [ $? -gt 0 ]; then echo "$devName: $testResult" # FIXME: what to do (pause, exit)? fi # do the diff dataDiff="`diff --unchanged-line-format='' --old-line-format='' --new-line-format='%L' ${TEMP_DIR}/prevDump.tmp ${TEMP_DIR}/curDump.tmp`" # dump actual, if any if [ ! -z "${dataDiff}" ]; then # dump differences echo "TIMER $curTimer" >> $outFile echo "$dataDiff" >> $outFile # and echo out echo "TIMER $curTimer" echo "$dataDiff" curTimer=0 fi # rotate dumps mv ${TEMP_DIR}/curDump.tmp ${TEMP_DIR}/prevDump.tmp done nut-2.7.2/tools/Makefile.am0000644000175000017500000000542512303134466012455 00000000000000# 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 IF they need to be, and all the nut-scanner sources need # to be moved out of a sub-directory into this directory. # # Anyway, for the time being, we force build in ./ before nut-scanner, # to have nutscan-{usb,snmp}.h built before going into the nut-scanner # sub-directory SUBDIRS = . nut-scanner EXTRA_DIST = nut-usbinfo.pl nut-recorder.sh gitlog2changelog.py 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 # 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 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; \ else \ echo "----------------------------------------------------------------------"; \ echo "Warning: Perl is not available."; \ echo "Skipping the USB helper files regeneration."; \ echo "----------------------------------------------------------------------"; \ fi .PHONY: nut-scanner-deps nut-scanner-snmp-deps nut-scanner-usb-deps nut-2.7.2/tools/gitlog2changelog.py0000755000175000017500000001001112303134466014200 00000000000000#!/usr/bin/env python # Copyright 2008 Marcus D. Hanwell # Minor changes for NUT by Charles Lepple # Distributed under the terms of the GNU General Public License v2 or later import string, re, os from textwrap import TextWrapper import sys rev_range = '' if len(sys.argv) > 1: base = sys.argv[1] rev_range = '%s..HEAD' % base # Execute git log with the desired command line options. fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r') # Create a ChangeLog file in the current directory. fout = open('ChangeLog', 'w') # Set up the loop variables in order to locate the blocks we want authorFound = False dateFound = False messageFound = False filesFound = False message = "" messageNL = False files = "" prevAuthorLine = "" wrapper = TextWrapper(initial_indent="\t", subsequent_indent="\t ") # The main part of the loop for line in fin: # The commit line marks the start of a new commit object. if line.startswith('commit'): # Start all over again... authorFound = False dateFound = False messageFound = False messageNL = False message = "" filesFound = False files = "" continue # Match the author line and extract the part we want elif 'Author:' in line: authorList = re.split(': ', line, 1) author = authorList[1] author = author[0:len(author)-1] authorFound = True # Match the date line elif 'Date:' in line: dateList = re.split(': ', line, 1) date = dateList[1] date = date[0:len(date)-1] dateFound = True # The Fossil-IDs are ignored: elif line.startswith(' Fossil-ID:') or line.startswith(' [[SVN:'): continue # The svn-id lines are ignored elif ' git-svn-id:' in line: continue # The sign off line is ignored too elif 'Signed-off-by' in line: continue # Extract the actual commit message for this commit elif authorFound & dateFound & messageFound == False: # Find the commit message if we can if len(line) == 1: if messageNL: messageFound = True else: messageNL = True elif len(line) == 4: messageFound = True else: if len(message) == 0: message = message + line.strip() else: message = message + " " + line.strip() # If this line is hit all of the files have been stored for this commit elif re.search('files? changed', line) >= 0: filesFound = True continue # Collect the files for this commit. FIXME: Still need to add +/- to files elif authorFound & dateFound & messageFound: fileList = re.split(' \| ', line, 2) if len(fileList) > 1: if len(files) > 0: files = files + ", " + fileList[0].strip() else: files = fileList[0].strip() # All of the parts of the commit have been found - write out the entry if authorFound & dateFound & messageFound & filesFound: # First the author line, only outputted if it is the first for that # author on this day authorLine = date + " " + author if len(prevAuthorLine) == 0: fout.write(authorLine + "\n\n") elif authorLine == prevAuthorLine: pass else: fout.write("\n" + authorLine + "\n\n") # Assemble the actual commit message line(s) and limit the line length # to 80 characters. commitLine = "* " + files + ": " + message # Write out the commit line fout.write(wrapper.fill(commitLine) + "\n") #Now reset all the variables ready for a new commit block. authorFound = False dateFound = False messageFound = False messageNL = False message = "" filesFound = False files = "" prevAuthorLine = authorLine # Close the input and output lines now that we are finished. fin.close() fout.close() nut-2.7.2/tools/nut-snmpinfo.py0000755000175000017500000001213012277355125013431 00000000000000#!/usr/bin/env python # Copyright (C) 2011 - Frederic Bohe # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # This program extracts all SNMP information related to NUT snmp-ups # drivers. import glob import re output_file_name="./nut-scanner/nutscan-snmp.h" output_file = open(output_file_name,'w') #expand #define constant def expand_define(filename,constant): ret_line = "" f = open(filename, 'r') for line in f: if constant in line and "#define" in line: line_without_carriage_return = re.sub("[\n\r]", "", line) line_with_single_blank = re.sub("[ \t]+", " ", line_without_carriage_return) define_line = line_with_single_blank.split(" "); #define_line[0] = "#define" #define_line[1] = const name #define_line[2...] = const value (may be other const name) if constant in define_line[1]: define_line.pop(0) #remove #define define_line.pop(0) #remove the constant name for elem in define_line: if elem[0] == "\"": clean_elem = re.sub("\"", "", elem) ret_line = ret_line + clean_elem else: ret_line = ret_line + expand_define(filename,elem); return ret_line output_file.write( "/* nutscan-snmp\n" ) output_file.write( " * Copyright (C) 2011 - Frederic Bohe \n" ) output_file.write( " *\n" ) output_file.write( " * This program is free software; you can redistribute it and/or modify\n" ) output_file.write( " * it under the terms of the GNU General Public License as published by\n" ) output_file.write( " * the Free Software Foundation; either version 2 of the License, or\n" ) output_file.write( " * (at your option) any later version.\n" ) output_file.write( " *\n" ) output_file.write( " * This program is distributed in the hope that it will be useful,\n" ) output_file.write( " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" ) output_file.write( " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" ) output_file.write( " * GNU General Public License for more details.\n" ) output_file.write( " *\n" ) output_file.write( " * You should have received a copy of the GNU General Public License\n" ) output_file.write( " * along with this program; if not, write to the Free Software\n" ) output_file.write( " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" ) output_file.write( " */\n" ) output_file.write( "\n" ) output_file.write( "#ifndef DEVSCAN_SNMP_H\n" ) output_file.write( "#define DEVSCAN_SNMP_H\n" ) output_file.write( "\n" ) output_file.write( "typedef struct {\n" ) output_file.write( " char * oid;\n" ) output_file.write( " char * mib;\n" ) output_file.write( " char * sysoid;\n" ) output_file.write( "} snmp_device_id_t;\n" ) output_file.write( "\n" ) output_file.write( "/* SNMP IDs device table */\n" ) output_file.write( "static snmp_device_id_t snmp_device_table[] = {\n" ) for filename in glob.glob('../drivers/*-mib.c'): list_of_line = open(filename,'r').read().split(';') for line in list_of_line: if "mib2nut_info_t" in line: #clean up line line2 = re.sub("[\n\t\r}]", "", line) # split line line = line2.split("{",1) #line[1] is the part between {} line2 = line[1].split(",") mib = line2[0] #line2[3] is the OID of the device model name which #could be made of #define const and string. source_oid = line2[3] #line2[5] is the SysOID of the device which #could be made of #define const and string. if len(line2) >= 6: source_sysoid = line2[5] else: source_sysoid = "NULL" #decode source_oid line = source_oid.lstrip(" ") line2 = line.split(" ") oid = "" for elem in line2: if elem[0] == "\"": clean_elem = re.sub("\"", "", elem) oid = oid+clean_elem else: oid = oid + expand_define(filename,elem); #decode source_sysoid line = source_sysoid.lstrip(" ") line = line.rstrip(" ") line2 = line.split(" ") sysoid = "" for elem in line2: if elem[0] == "\"": clean_elem = re.sub("\"", "", elem) sysoid = sysoid+clean_elem else: sysoid = sysoid + expand_define(filename,elem); if sysoid == "": sysoid = "NULL" else: sysoid = "\"" + sysoid + "\"" output_file.write( "\t{ \"" + oid + "\" , " + mib + ", " + sysoid + "},\n" ) output_file.write( " /* Terminating entry */\n" ) output_file.write( " { NULL, NULL, NULL}\n" ) output_file.write( "};\n" ) output_file.write( "#endif /* DEVSCAN_SNMP_H */\n" ) nut-2.7.2/tools/Makefile.in0000644000175000017500000005504612324034370012466 00000000000000# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # TODO: remove redundancies! VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = tools DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nut_arg_with.m4 \ $(top_srcdir)/m4/nut_check_asciidoc.m4 \ $(top_srcdir)/m4/nut_check_libavahi.m4 \ $(top_srcdir)/m4/nut_check_libfreeipmi.m4 \ $(top_srcdir)/m4/nut_check_libgd.m4 \ $(top_srcdir)/m4/nut_check_libltdl.m4 \ $(top_srcdir)/m4/nut_check_libneon.m4 \ $(top_srcdir)/m4/nut_check_libnetsnmp.m4 \ $(top_srcdir)/m4/nut_check_libnss.m4 \ $(top_srcdir)/m4/nut_check_libopenssl.m4 \ $(top_srcdir)/m4/nut_check_libpowerman.m4 \ $(top_srcdir)/m4/nut_check_libusb.m4 \ $(top_srcdir)/m4/nut_check_libwrap.m4 \ $(top_srcdir)/m4/nut_check_os.m4 \ $(top_srcdir)/m4/nut_report_feature.m4 \ $(top_srcdir)/m4/nut_type_socklen_t.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" A2X = @A2X@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ ASCIIDOC = @ASCIIDOC@ ASPELL = @ASPELL@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONFPATH = @CONFPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBLATEX = @DBLATEX@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOC_BUILD_LIST = @DOC_BUILD_LIST@ DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@ DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@ DRIVER_MAN_LIST = @DRIVER_MAN_LIST@ DRVPATH = @DRVPATH@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAVAHI_CFLAGS = @LIBAVAHI_CFLAGS@ LIBAVAHI_LIBS = @LIBAVAHI_LIBS@ LIBGD_CFLAGS = @LIBGD_CFLAGS@ LIBGD_LDFLAGS = @LIBGD_LDFLAGS@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@ LIBIPMI_LIBS = @LIBIPMI_LIBS@ LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@ LIBLTDL_LIBS = @LIBLTDL_LIBS@ LIBNEON_CFLAGS = @LIBNEON_CFLAGS@ LIBNEON_LIBS = @LIBNEON_LIBS@ LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@ LIBNETSNMP_LIBS = @LIBNETSNMP_LIBS@ LIBOBJS = @LIBOBJS@ LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@ LIBS = @LIBS@ LIBSSL_CFLAGS = @LIBSSL_CFLAGS@ LIBSSL_LIBS = @LIBSSL_LIBS@ LIBTOOL = @LIBTOOL@ LIBUSB_CFLAGS = @LIBUSB_CFLAGS@ LIBUSB_LIBS = @LIBUSB_LIBS@ LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@ LIBWRAP_LIBS = @LIBWRAP_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NETLIBS = @NETLIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NUT_NETVERSION = @NUT_NETVERSION@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_NAME = @OS_NAME@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIDPATH = @PIDPATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PORT = @PORT@ RANLIB = @RANLIB@ RUN_AS_GROUP = @RUN_AS_GROUP@ RUN_AS_USER = @RUN_AS_USER@ SBINDIR = @SBINDIR@ SED = @SED@ SERLIBS = @SERLIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STATEPATH = @STATEPATH@ STRIP = @STRIP@ SUN_LIBUSB = @SUN_LIBUSB@ TREE_VERSION = @TREE_VERSION@ VERSION = @VERSION@ WORDS_BIGENDIAN = @WORDS_BIGENDIAN@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ cgiexecdir = @cgiexecdir@ datadir = @datadir@ datarootdir = @datarootdir@ devddir = @devddir@ docdir = @docdir@ driverexecdir = @driverexecdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ hotplugdir = @hotplugdir@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemdsystemshutdowndir = @systemdsystemshutdowndir@ systemdsystemunitdir = @systemdsystemunitdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udevdir = @udevdir@ # 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 IF they need to be, and all the nut-scanner sources need # to be moved out of a sub-directory into this directory. # # Anyway, for the time being, we force build in ./ before nut-scanner, # to have nutscan-{usb,snmp}.h built before going into the nut-scanner # sub-directory SUBDIRS = . nut-scanner EXTRA_DIST = nut-usbinfo.pl nut-recorder.sh gitlog2changelog.py nut-snmpinfo.py all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tools/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic clean-libtool \ ctags ctags-recursive dist-hook distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am 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 # 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 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; \ else \ echo "----------------------------------------------------------------------"; \ echo "Warning: Perl is not available."; \ echo "Skipping the USB helper files regeneration."; \ echo "----------------------------------------------------------------------"; \ fi .PHONY: nut-scanner-deps nut-scanner-snmp-deps nut-scanner-usb-deps # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: nut-2.7.2/tools/nut-usbinfo.pl0000755000175000017500000002751612303725554013243 00000000000000#!/usr/bin/env perl # Current Version : 1.3 # Copyright (C) 2008 - 2012 dloic (loic.dardant AT gmail DOT com) # Copyright (C) 2008 - 2014 Arnaud Quette # Copyright (C) 2013 - 2014 Charles Lepple # # Based on the usbdevice.pl script, made for the Ubuntu Media Center # for the final use of the LIRC project. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # TODO list: # - rewrite using glob, as in other helper scripts # - manage deps in Makefile.am use File::Find; use strict; # path to scan for USB_DEVICE pattern my $scanPath="../drivers"; # Hotplug output file my $outputHotplug="../scripts/hotplug/libhid.usermap"; # udev output file my $outputUdev="../scripts/udev/nut-usbups.rules.in"; # BSD devd output file my $output_devd="../scripts/devd/nut-usb.conf.in"; # UPower output file 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 $GPL_header = "\ * Copyright (C) 2011 - Arnaud Quette \ *\ * This program is free software; you can redistribute it and/or modify\ * it under the terms of the GNU General Public License as published by\ * the Free Software Foundation; either version 2 of the License, or\ * (at your option) any later version.\ *\ * This program is distributed in the hope that it will be useful,\ * but WITHOUT ANY WARRANTY; without even the implied warranty of\ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\ * GNU General Public License for more details.\ *\ * You should have received a copy of the GNU General Public License\ * along with this program; if not, write to the Free Software\ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"; # array of products indexed by vendorID my %vendor; # contain for each vendor, its name (and...) my %vendorName; ################# MAIN ################# find(\&find_usbdevs,$scanPath); &gen_usb_files; ################# SUB METHOD ################# sub gen_usb_files { # Hotplug file header open my $outHotplug, ">$outputHotplug" || die "error $outputHotplug : $!"; print $outHotplug '# This file is generated and installed by the Network UPS Tools package.'."\n"; print $outHotplug "#\n"; print $outHotplug '# Sample entry (replace 0xVVVV and 0xPPPP with vendor ID and product ID respectively) :'."\n"; print $outHotplug '# libhidups 0x0003 0xVVVV 0xPPPP 0x0000 0x0000 0x00 0x00'; print $outHotplug ' 0x00 0x00 0x00 0x00 0x00000000'."\n"; print $outHotplug "#\n"; print $outHotplug '# usb module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi'; print $outHotplug ' bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass'; print $outHotplug ' bInterfaceProtocol driver_info'."\n"; # Udev file header open my $outUdev, ">$outputUdev" || die "error $outputUdev : $!"; print $outUdev '# This file is generated and installed by the Network UPS Tools package.'."\n\n"; print $outUdev 'ACTION!="add|change", GOTO="nut-usbups_rules_end"'."\n"; print $outUdev 'SUBSYSTEM=="usb_device", GOTO="nut-usbups_rules_real"'."\n"; print $outUdev 'SUBSYSTEM=="usb", GOTO="nut-usbups_rules_real"'."\n"; print $outUdev 'SUBSYSTEM!="usb", GOTO="nut-usbups_rules_end"'."\n\n"; print $outUdev 'LABEL="nut-usbups_rules_real"'."\n"; open my $out_devd, ">$output_devd" || die "error $output_devd : $!"; print $out_devd '# This file is generated and installed by the Network UPS Tools package.'."\n"; print $out_devd "# Homepage: http://www.networkupstools.org/\n\n"; # UPower file header open my $outputUPower, ">$outputUPower" || die "error $outputUPower : $!"; print $outputUPower '##############################################################################################################'."\n"; print $outputUPower '# Uninterruptible Power Supplies with USB HID interfaces'."\n#\n"; print $outputUPower '# to keep up to date, monitor: http://svn.debian.org/wsvn/nut/trunk/scripts/upower/95-upower-hid.rules'."\n\n"; print $outputUPower '# only support USB, else ignore'."\n".'SUBSYSTEM!="usb", GOTO="up_hid_end"'."\n\n"; print $outputUPower '# if usbraw device, ignore'."\n".'KERNEL!="hiddev*", GOTO="up_hid_end"'."\n\n"; print $outputUPower '# if an interface, ignore'."\n".'ENV{DEVTYPE}=="usb_interface", GOTO="up_hid_end"'."\n\n"; # Device scanner header open my $outputDevScanner, ">$outputDevScanner" || die "error $outputDevScanner : $!"; print $outputDevScanner '/* nutscan-usb'.$GPL_header."\n */\n\n"; print $outputDevScanner "#ifndef DEVSCAN_USB_H\n#define DEVSCAN_USB_H\n\n"; print $outputDevScanner "#include \n"; print $outputDevScanner "#include \"nut_stdint.h\"\t/* for uint16_t */\n\n"; # vid, pid, driver print $outputDevScanner "typedef struct {\n\tuint16_t\tvendorID;\n\tuint16_t\tproductID;\n\tchar*\tdriver_name;\n} usb_device_id_t;\n\n"; print $outputDevScanner "/* USB IDs device table */\nstatic usb_device_id_t usb_device_table[] = {\n\n"; # generate the file in alphabetical order (first for VendorID, then for ProductID) foreach my $vendorId (sort { lc $a cmp lc $b } keys %vendorName) { # Hotplug vendor header if ($vendorName{$vendorId}) { print $outHotplug "\n# ".$vendorName{$vendorId}."\n"; } # udev vendor header if ($vendorName{$vendorId}) { print $outUdev "\n# ".$vendorName{$vendorId}."\n"; } # devd vendor header if ($vendorName{$vendorId}) { print $out_devd "\n# ".$vendorName{$vendorId}."\n"; } # UPower vendor header flag $upowerMfrHeaderDone = 0; foreach my $productId (sort { lc $a cmp lc $b } keys %{$vendor{$vendorId}}) { # Hotplug device entry print $outHotplug "# ".$vendor{$vendorId}{$productId}{"comment"}."\n"; print $outHotplug "libhidups 0x0003 ".$vendorId." ".$productId." 0x0000 0x0000 0x00"; print $outHotplug " 0x00 0x00 0x00 0x00 0x00 0x00000000\n"; # udev device entry print $outUdev "# ".$vendor{$vendorId}{$productId}{"comment"}.' - '.$vendor{$vendorId}{$productId}{"driver"}."\n"; print $outUdev "ATTR{idVendor}==\"".removeHexPrefix($vendorId); print $outUdev "\", ATTR{idProduct}==\"".removeHexPrefix($productId)."\","; print $outUdev ' MODE="664", GROUP="@RUN_AS_GROUP@"'."\n"; # devd device entry print $out_devd "# ".$vendor{$vendorId}{$productId}{"comment"}.' - '.$vendor{$vendorId}{$productId}{"driver"}."\n"; print $out_devd "notify 100 {\n\tmatch \"system\"\t\t\"USB\";\n"; print $out_devd "\tmatch \"subsystem\"\t\"DEVICE\";\n"; print $out_devd "\tmatch \"type\"\t\t\"ATTACH\";\n"; print $out_devd "\tmatch \"vendor\"\t\t\"$vendorId\";\n"; # print $out_devd "\tmatch \"product\"\t\t\"$productId\";\n"; print $out_devd "\taction \"chgrp \@RUN_AS_GROUP\@ /dev/\$device-name*; chmod g+rw /dev/\$device-name*\";\n"; print $out_devd "};\n"; # UPower device entry (only for USB/HID devices!) if ($vendor{$vendorId}{$productId}{"driver"} eq "usbhid-ups") { if ($upowerMfrHeaderDone == 0) { # UPower vendor header if ($vendorName{$vendorId}) { $tmpOutputUPower = $tmpOutputUPower."\n# ".$vendorName{$vendorId}."\n"; } print $outputUPower "ATTRS{idVendor}==\"".removeHexPrefix($vendorId)."\", ENV{UPOWER_VENDOR}=\"".$vendorName{$vendorId}."\"\n"; $upowerMfrHeaderDone = 1; } $tmpOutputUPower = $tmpOutputUPower."ATTRS{idVendor}==\"".removeHexPrefix($vendorId); $tmpOutputUPower = $tmpOutputUPower."\", ATTRS{idProduct}==\"".removeHexPrefix($productId)."\","; $tmpOutputUPower = $tmpOutputUPower.' ENV{UPOWER_BATTERY_TYPE}="ups"'."\n"; } # Device scanner entry print $outputDevScanner "\t{ ".$vendorId.', '.$productId.", \"".$vendor{$vendorId}{$productId}{"driver"}."\" },\n"; } } # Udev footer print $outUdev "\n".'LABEL="nut-usbups_rules_end"'."\n"; # UPower... # ...flush device table print $outputUPower $tmpOutputUPower; # ...and print footer print $outputUPower "\n".'LABEL="up_hid_end"'."\n"; # Device scanner footer print $outputDevScanner "\t/* Terminating entry */\n\t{ -1, -1, NULL }\n};\n#endif /* DEVSCAN_USB_H */\n\n"; } sub find_usbdevs { # maybe there's an option to turn off all .* files, but anyway this is stupid return $File::Find::prune = 1 if ($_ eq '.svn') || ($_ =~ /^\.#/); my $nameFile=$_; my $lastComment=""; open my $file,$nameFile or die "error open file $nameFile"; while(my $line=<$file>) { # catch comment (should permit comment on the precedent or on the current line of USB_DEVICE declaration) if($line =~/\s*\/\*(.+)\*\/\s*$/) { $lastComment=$1; } if($line =~/^\s*\{\s*USB_DEVICE\((.+)\,(.+)\)\s*/) # for example : { USB_DEVICE(MGE_VENDORID, 0x0001)... } { my $VendorID=trim($1); my $ProductID=trim($2); my $VendorName=""; # special thing for backward declaration using #DEFINE # Format: # /* vendor name */ # #define VENDORID 0x???? if(!($VendorID=~/\dx(\d|\w)+/)) { open my $fh,$nameFile or die "error open file $nameFile"; while(my $data=<$fh>) { # catch Vendor Name if($data =~/\s*\/\*(.+)\*\/\s*$/) { $VendorName=$1; } # catch VendorID if ($data =~ /(#define|#DEFINE)\s+$VendorID\s+(\dx(\d|\w)+)/) { $VendorID=$2; last; } } } # same thing for the productID if(!($ProductID=~/\dx(\d|\w)+/)) { my $data = do { open my $fh, $nameFile or die "error open file $nameFile"; join '', <$fh> }; if ($data =~ /(#define|#DEFINE)\s+$ProductID\s+(\dx(\d|\w)+)/) { $ProductID=$2; } else { die "In file $nameFile, for product $ProductID, can't find the declaration of the constant"; } } # store date (to be optimized) # and don't overwritte actual vendor names with empty values if( (!$vendorName{$VendorID}) or (($vendorName{$VendorID} eq "") and ($VendorName ne "")) ) { $vendorName{$VendorID}=trim($VendorName); } $vendor{$VendorID}{$ProductID}{"comment"}=$lastComment; # process the driver name my $driver=$nameFile; if($nameFile=~/(.+)-hid\.c/) { $driver="usbhid-ups"; } # FIXME: make a generic matching rule *.c => * elsif ($nameFile eq "bcmxcp_usb.c") { $driver="bcmxcp_usb"; } elsif ($nameFile eq "tripplite_usb.c") { $driver="tripplite_usb"; } elsif ($nameFile eq "blazer_usb.c") { $driver="blazer_usb"; } elsif ($nameFile eq "richcomm_usb.c") { $driver="richcomm_usb"; } elsif ($nameFile eq "nutdrv_atcl_usb.c") { $driver="nutdrv_atcl_usb"; } elsif ($nameFile eq "riello_usb.c") { $driver="riello_usb"; } elsif ($nameFile eq "nutdrv_qx.c") { $driver="nutdrv_qx"; } else { die "Unknown driver type: $nameFile"; } $vendor{$VendorID}{$ProductID}{"driver"}=$driver; } } } sub removeHexPrefix { # make a local copy, not to alter the original entry my $string = $_[0]; $string =~ s/0x//; return $string; } sub trim { my($str) = shift =~ m!^\s*(.+?)\s*$!i; defined $str ? return $str : return ''; } nut-2.7.2/tools/nut-scanner/0000755000175000017500000000000012324034434012725 500000000000000nut-2.7.2/tools/nut-scanner/nutscan-init.c0000644000175000017500000000402512301203177015423 00000000000000/* nutscan-init.c: init functions for nut scanner library * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include int nutscan_avail_avahi = 0; int nutscan_avail_ipmi = 0; int nutscan_avail_nut = 0; int nutscan_avail_snmp = 0; int nutscan_avail_usb = 0; int nutscan_avail_xml_http = 0; int nutscan_load_usb_library(void); int nutscan_load_snmp_library(void); int nutscan_load_neon_library(void); int nutscan_load_avahi_library(void); int nutscan_load_ipmi_library(void); int nutscan_load_upsclient_library(void); void nutscan_init(void) { #ifdef WITH_USB nutscan_avail_usb = nutscan_load_usb_library(); #endif #ifdef WITH_SNMP nutscan_avail_snmp = nutscan_load_snmp_library(); #endif #ifdef WITH_NEON nutscan_avail_xml_http = nutscan_load_neon_library(); #endif #ifdef WITH_AVAHI nutscan_avail_avahi = nutscan_load_avahi_library(); #endif #ifdef WITH_FREEIPMI nutscan_avail_ipmi = nutscan_load_ipmi_library(); #endif nutscan_avail_nut = nutscan_load_upsclient_library(); } void nutscan_free(void) { if( nutscan_avail_usb ) { lt_dlexit(); } if( nutscan_avail_snmp ) { lt_dlexit(); } if( nutscan_avail_xml_http ) { lt_dlexit(); } if( nutscan_avail_avahi ) { lt_dlexit(); } if( nutscan_avail_ipmi ) { lt_dlexit(); } if( nutscan_avail_nut ) { lt_dlexit(); } } nut-2.7.2/tools/nut-scanner/nutscan-serial.h0000644000175000017500000000171712277355125015766 00000000000000/* nutscan-serial.h: helper functions to get serial devices name * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SCAN_SERIAL #define SCAN_SERIAL char ** nutscan_get_serial_ports_list(const char *ports_range); #endif nut-2.7.2/tools/nut-scanner/scan_ipmi.c0000644000175000017500000005053112277355125014771 00000000000000/* scan_ipmi.c: detect NUT supported Power Supply Units * * Copyright (C) * 2011 - 2012 Arnaud Quette * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut-scan.h" #ifdef WITH_IPMI #include "upsclient.h" #include #include #include #include #define NUT_IPMI_DRV_NAME "nut-ipmipsu" /* IPMI defines */ /* 5 seconds for establishing an IPMI connection */ #define IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT 5000 #define IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT 250 /* dynamic link library stuff */ static char * libname = "libfreeipmi"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; #ifdef HAVE_FREEIPMI_11X_12X /* Functions symbols remapping */ #define IPMI_FRU_CLOSE_DEVICE_ID "ipmi_fru_close_device_id" #define IPMI_FRU_CTX_DESTROY "ipmi_fru_ctx_destroy" #define IPMI_FRU_CTX_CREATE "ipmi_fru_ctx_create" #define IPMI_FRU_CTX_SET_FLAGS "ipmi_fru_ctx_set_flags" #define IPMI_FRU_OPEN_DEVICE_ID "ipmi_fru_open_device_id" #define IPMI_FRU_CTX_ERRORMSG "ipmi_fru_ctx_errormsg" #define IPMI_FRU_READ_DATA_AREA "ipmi_fru_read_data_area" #define IPMI_FRU_PARSE_NEXT "ipmi_fru_next" typedef ipmi_fru_ctx_t ipmi_fru_parse_ctx_t; typedef ipmi_sdr_ctx_t ipmi_sdr_cache_ctx_t; /* Functions remapping */ static void (*nut_ipmi_sdr_ctx_destroy) (ipmi_sdr_ctx_t ctx); #else /* HAVE_FREEIPMI_11X_12X */ #define IPMI_FRU_AREA_SIZE_MAX IPMI_FRU_PARSE_AREA_SIZE_MAX #define IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS #define IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION /* Functions symbols remapping */ #define IPMI_FRU_CLOSE_DEVICE_ID "ipmi_fru_parse_close_device_id" #define IPMI_FRU_CTX_DESTROY "ipmi_fru_parse_ctx_destroy" #define IPMI_FRU_CTX_CREATE "ipmi_fru_parse_ctx_create" #define IPMI_FRU_CTX_SET_FLAGS "ipmi_fru_parse_ctx_set_flags" #define IPMI_FRU_OPEN_DEVICE_ID "ipmi_fru_parse_open_device_id" #define IPMI_FRU_CTX_ERRORMSG "ipmi_fru_parse_ctx_errormsg" #define IPMI_FRU_READ_DATA_AREA "ipmi_fru_parse_read_data_area" #define IPMI_FRU_PARSE_NEXT "ipmi_fru_parse_next" /* Functions remapping */ static void (*nut_ipmi_sdr_cache_ctx_destroy) (ipmi_sdr_cache_ctx_t ctx); static void (*nut_ipmi_sdr_parse_ctx_destroy) (ipmi_sdr_parse_ctx_t ctx); #endif /* HAVE_FREEIPMI_11X_12X */ static int (*nut_ipmi_fru_close_device_id) (ipmi_fru_parse_ctx_t ctx); static void (*nut_ipmi_fru_ctx_destroy) (ipmi_fru_parse_ctx_t ctx); static ipmi_fru_parse_ctx_t (*nut_ipmi_fru_ctx_create) (ipmi_ctx_t ipmi_ctx); static int (*nut_ipmi_fru_ctx_set_flags) (ipmi_fru_parse_ctx_t ctx, unsigned int flags); static int (*nut_ipmi_fru_open_device_id) (ipmi_fru_parse_ctx_t ctx, uint8_t fru_device_id); static char * (*nut_ipmi_fru_ctx_errormsg) (ipmi_fru_parse_ctx_t ctx); static int (*nut_ipmi_fru_read_data_area) (ipmi_fru_parse_ctx_t ctx, unsigned int *area_type, unsigned int *area_length, void *areabuf, unsigned int areabuflen); static int (*nut_ipmi_fru_next) (ipmi_fru_parse_ctx_t ctx); static ipmi_ctx_t (*nut_ipmi_ctx_create) (void); static int (*nut_ipmi_ctx_find_inband) (ipmi_ctx_t ctx, ipmi_driver_type_t *driver_type, int disable_auto_probe, uint16_t driver_address, uint8_t register_spacing, const char *driver_device, unsigned int workaround_flags, unsigned int flags); static int (*nut_ipmi_ctx_open_outofband) (ipmi_ctx_t ctx, const char *hostname, const char *username, const char *password, uint8_t authentication_type, uint8_t privilege_level, unsigned int session_timeout, unsigned int retransmission_timeout, unsigned int workaround_flags, unsigned int flags); static int (*nut_ipmi_ctx_errnum) (ipmi_ctx_t ctx); static char * (*nut_ipmi_ctx_errormsg) (ipmi_ctx_t ctx); static int (*nut_ipmi_ctx_close) (ipmi_ctx_t ctx); static void (*nut_ipmi_ctx_destroy) (ipmi_ctx_t ctx); /* Internal functions */ static nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * sec); /* Return 0 on error */ int nutscan_load_ipmi_library() { if( dl_handle != NULL ) { /* if previous init failed */ if( dl_handle == (void *)1 ) { return 0; } /* init has already been done */ return 1; } if( lt_dlinit() != 0 ) { fprintf(stderr, "Error initializing lt_init\n"); return 0; } dl_handle = lt_dlopenext(libname); if (!dl_handle) { dl_error = lt_dlerror(); goto err; } /* Clear any existing error */ lt_dlerror(); *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #ifdef HAVE_FREEIPMI_11X_12X *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #else /* HAVE_FREEIPMI_11X_12X */ *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_cache_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_parse_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #endif /* HAVE_FREEIPMI_11X_12X */ *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, "ipmi_ctx_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, "ipmi_ctx_find_inband"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, "ipmi_ctx_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } return 1; err: fprintf(stderr, "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; } /* end of dynamic link library stuff */ /* Cleanup IPMI contexts */ #ifdef HAVE_FREEIPMI_11X_12X static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx, ipmi_sdr_ctx_t sdr_ctx) #else /* HAVE_FREEIPMI_11X_12X */ static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx, ipmi_sdr_cache_ctx_t sdr_cache_ctx, ipmi_sdr_parse_ctx_t sdr_parse_ctx) #endif /* HAVE_FREEIPMI_11X_12X */ { if (fru_parse_ctx) { (*nut_ipmi_fru_close_device_id) (fru_parse_ctx); (*nut_ipmi_fru_ctx_destroy) (fru_parse_ctx); } #ifdef HAVE_FREEIPMI_11X_12X if (sdr_ctx) { (*nut_ipmi_sdr_ctx_destroy) (sdr_ctx); } #else /* HAVE_FREEIPMI_11X_12X */ if (sdr_cache_ctx) { (*nut_ipmi_sdr_cache_ctx_destroy) (sdr_cache_ctx); } if (sdr_parse_ctx) { (*nut_ipmi_sdr_parse_ctx_destroy) (sdr_parse_ctx); } #endif /* HAVE_FREEIPMI_11X_12X */ } /* Return 1 if supported, 0 otherwise */ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) { int ret = -1; unsigned int area_type = 0; unsigned int area_length = 0; uint8_t areabuf[IPMI_FRU_AREA_SIZE_MAX+1]; ipmi_fru_parse_ctx_t fru_parse_ctx = NULL; #ifdef HAVE_FREEIPMI_11X_12X ipmi_sdr_ctx_t sdr_ctx = NULL; #else /* HAVE_FREEIPMI_11X_12X */ ipmi_sdr_cache_ctx_t sdr_cache_ctx = NULL; ipmi_sdr_parse_ctx_t sdr_parse_ctx = NULL; #endif /* HAVE_FREEIPMI_11X_12X */ /* Parse FRU information */ if (!(fru_parse_ctx = (*nut_ipmi_fru_ctx_create) (ipmi_ctx))) { fprintf(stderr, "Error with %s(): %s\n", IPMI_FRU_CTX_CREATE, (*nut_ipmi_ctx_errormsg)(ipmi_ctx)); return 0; } /* lots of motherboards calculate checksums incorrectly */ if ((*nut_ipmi_fru_ctx_set_flags) (fru_parse_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); #else nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx); #endif /* HAVE_FREEIPMI_11X_12X */ return 0; } if ((*nut_ipmi_fru_open_device_id) (fru_parse_ctx, ipmi_id) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); #else nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx); #endif /* HAVE_FREEIPMI_11X_12X */ return 0; } do { /* clear fields */ area_type = 0; area_length = 0; memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1); /* parse FRU buffer */ if ((*nut_ipmi_fru_read_data_area) (fru_parse_ctx, &area_type, &area_length, areabuf, IPMI_FRU_AREA_SIZE_MAX) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); #else nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx); #endif /* HAVE_FREEIPMI_11X_12X */ return 0; } if (area_length) { if (area_type == IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION) { /* Found a POWER_SUPPLY record */ #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); #else nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx); #endif /* HAVE_FREEIPMI_11X_12X */ return 1; } } } while ((ret = (*nut_ipmi_fru_next) (fru_parse_ctx)) == 1); /* No need for further errors checking */ #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); #else nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx); #endif /* HAVE_FREEIPMI_11X_12X */ return 0; } /* Check for IPMI support on a specific (local or remote) system * Return NULL on error, or a valid nutscan_device_t otherwise */ nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * ipmi_sec) { ipmi_ctx_t ipmi_ctx = NULL; nutscan_device_t * nut_dev = NULL; nutscan_device_t * current_nut_dev = NULL; int ret = -1; int ipmi_id = 0; char port_id[64]; if( !nutscan_avail_ipmi ) { return NULL; } /* Initialize the FreeIPMI library. */ if (!(ipmi_ctx = (*nut_ipmi_ctx_create) ())) { /* we have to force cleanup, since exit handler is not yet installed */ fprintf(stderr, "ipmi_ctx_create\n"); return NULL; } /* Are we scanning locally, or over the network? */ if (IPaddr == NULL) { /* FIXME: we need root right to access local IPMI! if (!ipmi_is_root ()) { fprintf(stderr, "IPMI scan: %s\n", ipmi_ctx_strerror (IPMI_ERR_PERMISSION)); } */ if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx, NULL, 0, /* don't disable auto-probe */ 0, 0, NULL, 0, /* workaround flags, none by default */ 0 /* flags */ )) < 0) { fprintf(stderr, "ipmi_ctx_find_inband: %s\n", (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); return NULL; } if (!ret) { /* No local IPMI device detected */ return NULL; } } else { #if 0 if (ipmi_sec->ipmi_version == IPMI_2_0) { /* FIXME: need processing?! * int parse_kg (void *out, unsigned int outlen, const char *in) * if ((rv = parse_kg (common_cmd_args_config->k_g, IPMI_MAX_K_G_LENGTH + 1, data->string)) < 0) * { * fprintf (stderr, "Config File Error: k_g input formatted incorrectly\n"); * exit (EXIT_FAILURE); * }*/ if ((ret = (*nut_ipmi_ctx_open_outofband_2_0) (ipmi_ctx, IPaddr, ipmi_sec->username, ipmi_sec->password, ipmi_sec->K_g_BMC_key, ??? (ipmi_sec->K_g_BMC_key) ? config->k_g_len : 0, ipmi_sec->privilege_level, ipmi_sec->cipher_suite_id, IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, ipmi_dev->workaround_flags, flags) < 0) { IPMI_MONITORING_DEBUG (("ipmi_ctx_open_outofband_2_0: %s", ipmi_ctx_errormsg (c->ipmi_ctx))); if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_USERNAME_INVALID) c->errnum = IPMI_MONITORING_ERR_USERNAME_INVALID; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID) c->errnum = IPMI_MONITORING_ERR_PASSWORD_INVALID; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT) c->errnum = IPMI_MONITORING_ERR_PRIVILEGE_LEVEL_INSUFFICIENT; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED) c->errnum = IPMI_MONITORING_ERR_PRIVILEGEL_LEVEL_CANNOT_BE_OBTAINED; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_K_G_INVALID) c->errnum = IPMI_MONITORING_ERR_K_G_INVALID; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CIPHER_SUITE_ID_UNAVAILABLE) c->errnum = IPMI_MONITORING_ERR_CIPHER_SUITE_ID_UNAVAILABLE; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT) c->errnum = IPMI_MONITORING_ERR_PASSWORD_VERIFICATION_TIMEOUT; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_2_0_UNAVAILABLE) c->errnum = IPMI_MONITORING_ERR_IPMI_2_0_UNAVAILABLE; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) c->errnum = IPMI_MONITORING_ERR_CONNECTION_TIMEOUT; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SESSION_TIMEOUT) c->errnum = IPMI_MONITORING_ERR_SESSION_TIMEOUT; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE || ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_ERROR) c->errnum = IPMI_MONITORING_ERR_IPMI_ERROR; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BMC_BUSY) c->errnum = IPMI_MONITORING_ERR_BMC_BUSY; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_OUT_OF_MEMORY) c->errnum = IPMI_MONITORING_ERR_OUT_OF_MEMORY; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID) c->errnum = IPMI_MONITORING_ERR_HOSTNAME_INVALID; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PARAMETERS) c->errnum = IPMI_MONITORING_ERR_PARAMETERS; else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SYSTEM_ERROR) c->errnum = IPMI_MONITORING_ERR_SYSTEM_ERROR; else c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR; return (-1); } } else { /* Not IPMI 2.0 */ #endif /* 0 */ /* Fall back to IPMI 1.5 */ if ((ret = (*nut_ipmi_ctx_open_outofband) (ipmi_ctx, IPaddr, ipmi_sec->username, ipmi_sec->password, ipmi_sec->authentication_type, ipmi_sec->privilege_level, IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, ipmi_sec->workaround_flags, IPMI_FLAGS_DEFAULT )) < 0) { /* No IPMI device detected on this host! if ((*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_AUTHENTICATION_TYPE_UNAVAILABLE || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) { */ /* FIXME: don't log timeout errors */ fprintf(stderr, "nut_ipmi_ctx_open_outofband: %s\n", (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); return NULL; /*}*/ } } /* Loop through all possible components */ for (ipmi_id = 0 ; ipmi_id <= IPMI_FRU_DEVICE_ID_MAX ; ipmi_id++) { if (is_ipmi_device_supported(ipmi_ctx, ipmi_id)) { if ( (nut_dev = nutscan_new_device()) == NULL ) { fprintf(stderr,"Memory allocation error\n"); nutscan_free_device(current_nut_dev); break; } /* Fill the device structure (sufficient with driver and port) */ nut_dev->type = TYPE_IPMI; nut_dev->driver = strdup(NUT_IPMI_DRV_NAME); if (IPaddr == NULL) { sprintf(port_id, "id%x", ipmi_id); } else { /* FIXME: also check against "localhost" and its IPv{4,6} */ sprintf(port_id, "id%x@%s", ipmi_id, IPaddr); } nut_dev->port = strdup(port_id); /* FIXME: also dump device.serial? * using drivers/libfreeipmi_get_board_info() */ current_nut_dev = nutscan_add_device_to_device( current_nut_dev, nut_dev); memset (port_id, 0, sizeof(port_id)); } } /* Final cleanup */ if (ipmi_ctx) { (*nut_ipmi_ctx_close) (ipmi_ctx); (*nut_ipmi_ctx_destroy) (ipmi_ctx); } return current_nut_dev; } /* General IPMI scan entry point: scan 1 to n devices, local or remote, * for IPMI support * Return NULL on error, or a valid nutscan_device_t otherwise */ nutscan_device_t * nutscan_scan_ipmi(const char * start_ip, const char * stop_ip, nutscan_ipmi_t * sec) { nutscan_ip_iter_t ip; char * ip_str = NULL; nutscan_ipmi_t * tmp_sec; nutscan_device_t * nut_dev = NULL; nutscan_device_t * current_nut_dev = NULL; if( !nutscan_avail_ipmi ) { return NULL; } /* Are we scanning locally, or through the network? */ if (start_ip == NULL) { /* Local PSU scan */ current_nut_dev = nutscan_scan_ipmi_device(NULL, NULL); } else { ip_str = nutscan_ip_iter_init(&ip, start_ip, stop_ip); while(ip_str != NULL) { tmp_sec = malloc(sizeof(nutscan_ipmi_t)); memcpy(tmp_sec, sec, sizeof(nutscan_ipmi_t)); if ((current_nut_dev = nutscan_scan_ipmi_device(ip_str, tmp_sec)) != NULL) { /* Store the positive result */ current_nut_dev = nutscan_add_device_to_device(current_nut_dev, nut_dev); } /* Prepare the next iteration */ ip_str = nutscan_ip_iter_inc(&ip); }; } return nutscan_rewind_device(current_nut_dev); } #else /* WITH_IPMI */ /* stub function */ nutscan_device_t * nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec) { return NULL; } #endif /* WITH_IPMI */ nut-2.7.2/tools/nut-scanner/nut-scanner.c0000644000175000017500000004145412301203177015253 00000000000000/* nut-scanner.c: a tool to detect NUT supported devices * * Copyright (C) * 2011 - 2012 Arnaud Quette * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "common.h" #include "nut_version.h" #include #include #ifdef HAVE_PTHREAD #include #endif #include "nut-scan.h" #define DEFAULT_TIMEOUT 5 #define ERR_BAD_OPTION (-1) const char optstring[] = "?ht:s:e:E:c:l:u:W:X:w:x:p:b:B:d:D:CUSMOAm:NPqIVa"; #ifdef HAVE_GETOPT_LONG const struct option longopts[] = {{ "timeout",required_argument,NULL,'t' }, { "start_ip",required_argument,NULL,'s' }, { "end_ip",required_argument,NULL,'e' }, { "eaton_serial",required_argument,NULL,'E' }, { "mask_cidr",required_argument,NULL,'m' }, { "community",required_argument,NULL,'c' }, { "secLevel",required_argument,NULL,'l' }, { "secName",required_argument,NULL,'u' }, { "authPassword",required_argument,NULL,'W' }, { "privPassword",required_argument,NULL,'X' }, { "authProtocol",required_argument,NULL,'w' }, { "privProtocol",required_argument,NULL,'x' }, { "username",required_argument,NULL,'b' }, { "password",required_argument,NULL,'B' }, { "authType",required_argument,NULL,'d' }, { "cipher_suite_id",required_argument,NULL,'D' }, { "port",required_argument,NULL,'p' }, { "complete_scan",no_argument,NULL,'C' }, { "usb_scan",no_argument,NULL,'U' }, { "snmp_scan",no_argument,NULL,'S' }, { "xml_scan",no_argument,NULL,'M' }, { "oldnut_scan",no_argument,NULL,'O' }, { "avahi_scan",no_argument,NULL,'A' }, { "ipmi_scan",no_argument,NULL,'I' }, { "disp_nut_conf",no_argument,NULL,'N' }, { "disp_parsable",no_argument,NULL,'P' }, { "quiet",no_argument,NULL,'q' }, { "help",no_argument,NULL,'h' }, { "version",no_argument,NULL,'V' }, { "available",no_argument,NULL,'a' }, {NULL,0,NULL,0}}; #else #define getopt_long(a,b,c,d,e) getopt(a,b,c) #endif /* HAVE_GETOPT_LONG */ static nutscan_device_t *dev[TYPE_END]; static long timeout = DEFAULT_TIMEOUT*1000*1000; /* in usec */ static char * start_ip = NULL; static char * end_ip = NULL; static char * port = NULL; static char * serial_ports = NULL; #ifdef HAVE_PTHREAD static pthread_t thread[TYPE_END]; static void * run_usb(void * arg) { dev[TYPE_USB] = nutscan_scan_usb(); return NULL; } static void * run_snmp(void * arg) { nutscan_snmp_t * sec = (nutscan_snmp_t *)arg; dev[TYPE_SNMP] = nutscan_scan_snmp(start_ip,end_ip,timeout,sec); return NULL; } static void * run_xml(void * arg) { dev[TYPE_XML] = nutscan_scan_xml_http(timeout); return NULL; } static void * run_nut_old(void * arg) { dev[TYPE_NUT] = nutscan_scan_nut(start_ip,end_ip,port,timeout); return NULL; } static void * run_avahi(void * arg) { dev[TYPE_AVAHI] = nutscan_scan_avahi(timeout); return NULL; } static void * run_ipmi(void * arg) { nutscan_ipmi_t * sec = (nutscan_ipmi_t *)arg; dev[TYPE_IPMI] = nutscan_scan_ipmi(start_ip,end_ip,sec); return NULL; } static void * run_eaton_serial(void * arg) { dev[TYPE_EATON_SERIAL] = nutscan_scan_eaton_serial (serial_ports); return NULL; } #endif /* HAVE_PTHREAD */ int printq(int quiet,const char *fmt, ...) { va_list ap; int ret; if(quiet) { return 0; } va_start(ap, fmt); ret = vprintf(fmt, ap); va_end(ap); return ret; } int main(int argc, char *argv[]) { nutscan_snmp_t snmp_sec; nutscan_ipmi_t ipmi_sec; int opt_ret; char * cidr = NULL; int allow_all = 0; int allow_usb = 0; int allow_snmp = 0; int allow_xml = 0; int allow_oldnut = 0; int allow_avahi = 0; int allow_ipmi = 0; int allow_eaton_serial = 0; /* MUST be requested explicitely! */ int quiet = 0; void (*display_func)(nutscan_device_t * device); int ret_code = EXIT_SUCCESS; memset(&snmp_sec, 0, sizeof(snmp_sec)); memset(&ipmi_sec, 0, sizeof(ipmi_sec)); /* Set the default values for IPMI */ ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_MD5; ipmi_sec.ipmi_version = IPMI_1_5; /* default to IPMI 1.5, if not otherwise specified */ ipmi_sec.cipher_suite_id = 3; /* default to HMAC-SHA1; HMAC-SHA1-96; AES-CBC-128 */ ipmi_sec.privilege_level = IPMI_PRIVILEGE_LEVEL_ADMIN; /* should be sufficient */ nutscan_init(); display_func = nutscan_display_ups_conf; while((opt_ret = getopt_long(argc, argv, optstring, longopts, NULL))!=-1) { switch(opt_ret) { case 't': timeout = atol(optarg)*1000*1000; /*in usec*/ if( timeout == 0 ) { fprintf(stderr,"Illegal timeout value, using default %ds\n", DEFAULT_TIMEOUT); timeout = DEFAULT_TIMEOUT*1000*1000; } break; case 's': start_ip = strdup(optarg); end_ip = start_ip; break; case 'e': end_ip = strdup(optarg); break; case 'E': serial_ports = strdup(optarg); allow_eaton_serial = 1; break; case 'm': cidr = strdup(optarg); break; case 'c': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.community = strdup(optarg); break; case 'l': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.secLevel = strdup(optarg); break; case 'u': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.secName = strdup(optarg); break; case 'W': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.authPassword = strdup(optarg); break; case 'X': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.privPassword = strdup(optarg); break; case 'w': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.authProtocol = strdup(optarg); break; case 'x': if(!nutscan_avail_snmp) { goto display_help; } snmp_sec.privProtocol = strdup(optarg); break; case 'S': if(!nutscan_avail_snmp) { goto display_help; } allow_snmp = 1; break; case 'b': if(!nutscan_avail_ipmi) { goto display_help; } ipmi_sec.username = strdup(optarg); break; case 'B': if(!nutscan_avail_ipmi) { goto display_help; } ipmi_sec.password = strdup(optarg); break; case 'd': if(!nutscan_avail_ipmi) { goto display_help; } if (!strcmp(optarg, "NONE")) { ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_NONE; } else if (!strcmp(optarg, "STRAIGHT_PASSWORD_KEY")) { ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY; } else if (!strcmp(optarg, "MD2")) { ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_MD2; } else if (!strcmp(optarg, "MD5")) { ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_MD5; } else { fprintf(stderr,"Unknown authentication type (%s). Defaulting to MD5\n", optarg); } break; case 'D': if(!nutscan_avail_ipmi) { goto display_help; } ipmi_sec.cipher_suite_id = atoi(optarg); /* Force IPMI 2.0! */ ipmi_sec.ipmi_version = IPMI_2_0; break; case 'p': port = strdup(optarg); break; case 'C': allow_all = 1; break; case 'U': if(!nutscan_avail_usb) { goto display_help; } allow_usb = 1; break; case 'M': if(!nutscan_avail_xml_http) { goto display_help; } allow_xml = 1; break; case 'O': allow_oldnut = 1; break; case 'A': if(!nutscan_avail_avahi) { goto display_help; } allow_avahi = 1; break; case 'I': if(!nutscan_avail_ipmi) { goto display_help; } allow_ipmi = 1; break; case 'N': display_func = nutscan_display_ups_conf; break; case 'P': display_func = nutscan_display_parsable; break; case 'q': quiet = 1; break; case 'V': printf("Network UPS Tools - %s\n", NUT_VERSION_MACRO); exit(EXIT_SUCCESS); case 'a': printf("OLDNUT\n"); if(nutscan_avail_usb) { printf("USB\n"); } if(nutscan_avail_snmp) { printf("SNMP\n"); } if(nutscan_avail_xml_http) { printf("XML\n"); } if(nutscan_avail_avahi) { printf("AVAHI\n"); } if(nutscan_avail_ipmi) { printf("IPMI\n"); } printf("EATON_SERIAL\n"); exit(EXIT_SUCCESS); case '?': ret_code = ERR_BAD_OPTION; case 'h': default: display_help: puts("nut-scanner : detecting available power devices.\n"); puts("OPTIONS:"); printf(" -C, --complete_scan: Scan all available devices (default).\n"); if( nutscan_avail_usb ) { printf(" -U, --usb_scan: Scan USB devices.\n"); } if( nutscan_avail_snmp ) { printf(" -S, --snmp_scan: Scan SNMP devices.\n"); } if( nutscan_avail_xml_http ) { printf(" -M, --xml_scan: Scan XML/HTTP devices.\n"); } printf(" -O, --oldnut_scan: Scan NUT devices (old method).\n"); if( nutscan_avail_avahi ) { printf(" -A, --avahi_scan: Scan NUT devices (avahi method).\n"); } if( nutscan_avail_ipmi ) { printf(" -I, --ipmi_scan: Scan IPMI devices.\n"); } printf(" -E, --eaton_serial : Scan serial Eaton devices (XCP, SHUT and Q1).\n"); printf("\nNetwork specific options:\n"); printf(" -t, --timeout : network operation timeout (default %d).\n",DEFAULT_TIMEOUT); printf(" -s, --start_ip : First IP address to scan.\n"); printf(" -e, --end_ip : Last IP address to scan.\n"); printf(" -m, --mask_cidr : Give a range of IP using CIDR notation.\n"); if( nutscan_avail_snmp ) { printf("\nSNMP v1 specific options:\n"); printf(" -c, --community : Set SNMP v1 community name (default = public)\n"); printf("\nSNMP v3 specific options:\n"); printf(" -l, --secLevel : Set the securityLevel used for SNMPv3 messages (allowed values: noAuthNoPriv,authNoPriv,authPriv)\n"); printf(" -u, --secName : Set the securityName used for authenticated SNMPv3 messages (mandatory if you set secLevel. No default)\n"); printf(" -w, --authProtocol : Set the authentication protocol (MD5 or SHA) used for authenticated SNMPv3 messages (default=MD5)\n"); printf(" -W, --authPassword : Set the authentication pass phrase used for authenticated SNMPv3 messages (mandatory if you set secLevel to authNoPriv or authPriv)\n"); printf(" -x, --privProtocol : Set the privacy protocol (DES or AES) used for encrypted SNMPv3 messages (default=DES)\n"); printf(" -X, --privPassword : Set the privacy pass phrase used for encrypted SNMPv3 messages (mandatory if you set secLevel to authPriv)\n"); } if( nutscan_avail_ipmi ) { printf("\nIPMI over LAN specific options:\n"); printf(" -b, --username : Set the username used for authenticating IPMI over LAN connections (mandatory for IPMI over LAN. No default)\n"); /* Specify the username to use when authenticating with the remote host. If not specified, a null (i.e. anonymous) username is assumed. The user must have * at least ADMIN privileges in order for this tool to operate fully. */ printf(" -B, --password : Specify the password to use when authenticationg with the remote host (mandatory for IPMI over LAN. No default)\n"); /* Specify the password to use when authenticationg with the remote host. If not specified, a null password is assumed. Maximum password length is 16 for IPMI * 1.5 and 20 for IPMI 2.0. */ printf(" -d, --authType : Specify the IPMI 1.5 authentication type to use (NONE, STRAIGHT_PASSWORD_KEY, MD2, and MD5) with the remote host (default=MD5)\n"); printf(" -D, --cipher_suite_id : Specify the IPMI 2.0 cipher suite ID to use, for authentication, integrity, and confidentiality (default=3)\n"); } printf("\nNUT specific options:\n"); printf(" -p, --port : Port number of remote NUT upsd\n"); printf("\ndisplay specific options:\n"); printf(" -N, --disp_nut_conf: Display result in the ups.conf format\n"); printf(" -P, --disp_parsable: Display result in a parsable format\n"); printf("\nMiscellaneous options:\n"); printf(" -V, --version: Display NUT version\n"); printf(" -a, --available: Display available bus that can be scanned\n"); printf(" -q, --quiet: Display only scan result. No information on currently scanned bus is displayed.\n"); return ret_code; } } if( cidr ) { nutscan_cidr_to_ip(cidr, &start_ip, &end_ip); } if( !allow_usb && !allow_snmp && !allow_xml && !allow_oldnut && !allow_avahi && !allow_ipmi && !allow_eaton_serial) { allow_all = 1; } if( allow_all ) { allow_usb = 1; allow_snmp = 1; allow_xml = 1; allow_oldnut = 1; allow_avahi = 1; allow_ipmi = 1; /* BEWARE: allow_all does not include allow_eaton_serial! */ } if( allow_usb && nutscan_avail_usb ) { printq(quiet,"Scanning USB bus.\n"); #ifdef HAVE_PTHREAD if(pthread_create(&thread[TYPE_USB],NULL,run_usb,NULL)) { nutscan_avail_usb = 0; } #else dev[TYPE_USB] = nutscan_scan_usb(); #endif /* HAVE_PTHREAD */ } if( allow_snmp && nutscan_avail_snmp ) { if( start_ip == NULL ) { printq(quiet,"No start IP, skipping SNMP\n"); nutscan_avail_snmp = 0; } else { printq(quiet,"Scanning SNMP bus.\n"); #ifdef HAVE_PTHREAD if( pthread_create(&thread[TYPE_SNMP],NULL,run_snmp,&snmp_sec)) { nutscan_avail_snmp = 0; } #else dev[TYPE_SNMP] = nutscan_scan_snmp(start_ip,end_ip,timeout,&snmp_sec); #endif /* HAVE_PTHREAD */ } } if( allow_xml && nutscan_avail_xml_http) { printq(quiet,"Scanning XML/HTTP bus.\n"); #ifdef HAVE_PTHREAD if(pthread_create(&thread[TYPE_XML],NULL,run_xml,NULL)) { nutscan_avail_xml_http = 0; } #else dev[TYPE_XML] = nutscan_scan_xml_http(timeout); #endif /* HAVE_PTHREAD */ } if( allow_oldnut && nutscan_avail_nut) { if( start_ip == NULL ) { printq(quiet,"No start IP, skipping NUT bus (old connect method)\n"); nutscan_avail_nut = 0; } else { printq(quiet,"Scanning NUT bus (old connect method).\n"); #ifdef HAVE_PTHREAD if(pthread_create(&thread[TYPE_NUT],NULL,run_nut_old,NULL)) { nutscan_avail_nut = 0; } #else dev[TYPE_NUT] = nutscan_scan_nut(start_ip,end_ip,port,timeout); #endif /* HAVE_PTHREAD */ } } if( allow_avahi && nutscan_avail_avahi) { printq(quiet,"Scanning NUT bus (avahi method).\n"); #ifdef HAVE_PTHREAD if(pthread_create(&thread[TYPE_AVAHI],NULL,run_avahi,NULL)) { nutscan_avail_avahi = 0; } #else dev[TYPE_AVAHI] = nutscan_scan_avahi(timeout); #endif /* HAVE_PTHREAD */ } if( allow_ipmi && nutscan_avail_ipmi) { printq(quiet,"Scanning IPMI bus.\n"); #ifdef HAVE_PTHREAD if(pthread_create(&thread[TYPE_IPMI],NULL,run_ipmi,&ipmi_sec)) { nutscan_avail_ipmi = 0; } #else dev[TYPE_IPMI] = nutscan_scan_ipmi(start_ip,end_ip,&ipmi_sec); #endif /* HAVE_PTHREAD */ } /* Eaton serial scan */ if (allow_eaton_serial) { printq(quiet,"Scanning serial bus for Eaton devices.\n"); #ifdef HAVE_PTHREAD pthread_create(&thread[TYPE_EATON_SERIAL], NULL, run_eaton_serial, serial_ports); /* FIXME: check return code */ #else dev[TYPE_EATON_SERIAL] = nutscan_scan_eaton_serial (serial_ports); #endif /* HAVE_PTHREAD */ } #ifdef HAVE_PTHREAD if( allow_usb && nutscan_avail_usb ) { pthread_join(thread[TYPE_USB],NULL); } if( allow_snmp && nutscan_avail_snmp ) { pthread_join(thread[TYPE_SNMP],NULL); } if( allow_xml && nutscan_avail_xml_http ) { pthread_join(thread[TYPE_XML],NULL); } if( allow_oldnut && nutscan_avail_nut ) { pthread_join(thread[TYPE_NUT],NULL); } if( allow_avahi && nutscan_avail_avahi ) { pthread_join(thread[TYPE_AVAHI],NULL); } if( allow_ipmi && nutscan_avail_ipmi ) { pthread_join(thread[TYPE_IPMI],NULL); } if (allow_eaton_serial) { pthread_join(thread[TYPE_EATON_SERIAL],NULL); } #endif /* HAVE_PTHREAD */ display_func(dev[TYPE_USB]); nutscan_free_device(dev[TYPE_USB]); display_func(dev[TYPE_SNMP]); nutscan_free_device(dev[TYPE_SNMP]); display_func(dev[TYPE_XML]); nutscan_free_device(dev[TYPE_XML]); display_func(dev[TYPE_NUT]); nutscan_free_device(dev[TYPE_NUT]); display_func(dev[TYPE_AVAHI]); nutscan_free_device(dev[TYPE_AVAHI]); display_func(dev[TYPE_IPMI]); nutscan_free_device(dev[TYPE_IPMI]); display_func(dev[TYPE_EATON_SERIAL]); nutscan_free_device(dev[TYPE_EATON_SERIAL]); nutscan_free(); return EXIT_SUCCESS; } nut-2.7.2/tools/nut-scanner/Makefile.am0000644000175000017500000000325412303134466014710 00000000000000BUILT_SOURCES = nutscan-usb.h nutscan-snmp.h nutscan-usb.h nutscan-snmp.h: cd ..; $(MAKE) $(AM_MAKEFLAGS) nut-scanner-deps # Only build nut-scanner, and its library, if libltdl was found (required!) if WITH_LIBLTDL bin_PROGRAMS = nut-scanner lib_LTLIBRARIES = libnutscan.la endif libnutscan_la_SOURCES = scan_nut.c scan_ipmi.c \ nutscan-device.c nutscan-ip.c nutscan-display.c \ nutscan-init.c scan_usb.c scan_snmp.c scan_xml_http.c \ scan_avahi.c scan_eaton_serial.c nutscan-serial.c \ $(top_srcdir)/drivers/serial.c \ $(top_srcdir)/drivers/bcmxcp_ser.c \ $(top_srcdir)/common/common.c libnutscan_la_LIBADD = $(NETLIBS) $(LIBLTDL_LIBS) libnutscan_la_LDFLAGS = $(SERLIBS) -version-info 1:0:0 libnutscan_la_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include $(LIBLTDL_CFLAGS) -I$(top_srcdir)/drivers nut_scanner_SOURCES = nut-scanner.c nut_scanner_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include nut_scanner_LDADD = libnutscan.la ../../common/libcommon.la if WITH_SSL libnutscan_la_CFLAGS += $(LIBSSL_CFLAGS) libnutscan_la_LIBADD += $(LIBSSL_LIBS) endif if WITH_USB libnutscan_la_CFLAGS += $(LIBUSB_CFLAGS) endif if WITH_SNMP libnutscan_la_CFLAGS += $(LIBNETSNMP_CFLAGS) endif if WITH_NEON libnutscan_la_CFLAGS += $(LIBNEON_CFLAGS) endif if WITH_AVAHI libnutscan_la_CFLAGS += $(LIBAVAHI_CFLAGS) endif if WITH_IPMI libnutscan_la_CFLAGS += $(LIBIPMI_CFLAGS) endif dist_noinst_HEADERS = nutscan-usb.h nutscan-snmp.h if WITH_DEV include_HEADERS = nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h else dist_noinst_HEADERS += nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h nutscan-serial.h endif CLEANFILES = nutscan-usb.h nutscan-snmp.h nut-2.7.2/tools/nut-scanner/README0000644000175000017500000000511412277355125013540 00000000000000NUT device discovery ==================== Introduction ------------ linkman:nut-scanner[8] is available to discover supported NUT devices (USB, SNMP, Eaton XML/HTTP and IPMI) and NUT servers (using Avahi or the classic connection method). This tool actually use a library, called *libnutscan*, to perform actual processing. Client access library ~~~~~~~~~~~~~~~~~~~~~ The nutscan library can be linked into other programs to give access to NUT discovery. Both static and shared versions are provided. linkman:nut-scanner[8] is provided as an example of how to use the nutscan functions. Here is a simple example that scans for USB devices, and use its own iteration function to display results: #include #include #include /* Only enable USB scan */ #define HAVE_USB_H #include "nut-scan.h" int main() { nutscan_options_t * opt; nutscan_device_t *device; if ((device = nutscan_scan_usb()) == NULL) { printf("No device found\n"); exit(EXIT_FAILURE); } /* Rewind the list */ while(device->prev != NULL) { device = device->prev; } /* Print results */ do { printf("USB device found\n\tdriver: \"%s\"\n\tport: \"%s\"\n", device->driver, device->port); /* process options (serial number, bus, ...) */ opt = &(device->opt); do { if( opt->option != NULL ) { printf("\t%s",opt->option); if( opt->value != NULL ) { printf(": \"%s\"", opt->value); } printf("\n"); } opt = opt->next; } while( opt != NULL ); device = device->next; } while( device != NULL ); exit(EXIT_SUCCESS); } This library file and the associated header files are not installed by default. You must `./configure --with-lib` to enable building and installing these files. The libraries can then be built and installed with `make` and `make install` as usual. This must be done before building other (non-NUT) programs which depend on them. For more information, refer to the linkman:nutscan[3], manual page and the various link:man/index.html#devscan[nutscan_*(3)] functions documentation referenced in the same file. Configuration helpers ~~~~~~~~~~~~~~~~~~~~~ NUT provides helper scripts to ease the configuration step of your program, by detecting the right compilation and link flags. For more information, refer to a <>. Python ------ Python support for NUT discovery features is not yet available. Perl ---- Perl support for NUT discovery features is not yet available. Java ---- Java support for NUT discovery features is not yet available. nut-2.7.2/tools/nut-scanner/nutscan-serial.c0000644000175000017500000001202612301203177015737 00000000000000/* nutscan-serial.c: helper functions to get serial devices name * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "nutscan-serial.h" #include #include #include #include "nut_platform.h" #ifdef WIN32 /* Windows: all serial port names start with "COM" */ #define SERIAL_PORT_PREFIX "COM" #else /* Unix: all serial port names start with "/dev/tty" */ #define SERIAL_PORT_PREFIX "/dev/tty" #endif #define ERR_OUT_OF_BOUND "Serial port range out of bound (must be 0 to 9 or a to z depending on your system)\n" typedef struct { char * name; char auto_start_port; char auto_stop_port; } device_portname_t; device_portname_t device_portname[] = { #ifdef NUT_PLATFORM_HPUX /* the first number seems to be a card instance, the second number seems to be a port number */ { "/dev/tty0p%c", '0', '9' }, { "/dev/tty1p%c", '0', '9' }, /* osf/1 and Digital UNIX style */ { "/dev/tty0%c", '0', '9' }, #endif #ifdef NUT_PLATFORM_SOLARIS { "/dev/tty%c", 'a', 'z' }, #endif #ifdef NUT_PLATFORM_AIX { "/dev/tty%c", '0', '9' }, #endif #ifdef NUT_PLATFORM_LINUX { "/dev/ttyS%c", '0', '9' }, { "/dev/ttyUSB%c", '0', '9' }, #endif #ifdef NUT_PLATFORM_MS_WINDOWS { "COM%c", '1', '9'}, #endif /* SGI IRIX */ /* { "/dev/ttyd%i", "=" }, */ /* { "/dev/ttyf%i", "=" }, */ /* FIXME: Mac OS X has no serial port, but maybe ttyUSB? */ { NULL, 0 } }; /* Return 1 if port_name is a full path name to a serial port, * as per SERIAL_PORT_PREFIX */ static int is_serial_port_path(const char * port_name) { if (!strncmp(port_name, SERIAL_PORT_PREFIX, strlen(SERIAL_PORT_PREFIX))) { return 1; } return 0; } /* Add "port" to "list" */ static char ** add_port(char ** list, char * port) { char ** res; int count = 0; if(list == NULL) { count = 0; } else { while(list[count] != NULL) { count++; } } /*+1 to get the number of port from the index nb_ports*/ /*+1 for the terminal NULL */ res = realloc(list,(count+1+1)*sizeof(char*)); if( res == NULL ) { return NULL; } res[count] = strdup(port); res[count+1] = NULL; return res; } /* Return a list of serial ports name, in 'ports_list', according to the OS, * the provided 'ports_range', and the number of available ports */ char ** nutscan_get_serial_ports_list(const char *ports_range) { char start_port = 0; char stop_port = 0; char current_port = 0; char * list_sep_ptr = NULL; char ** ports_list = NULL; char str_tmp[128]; char * tok; device_portname_t *cur_device = NULL; char * saveptr = NULL; char * range; int flag_auto = 0; /* 1) check ports_list */ if ((ports_range == NULL) || (!strncmp(ports_range, "auto", 4))) { flag_auto = 1; } else { range = strdup(ports_range); /* we have a list: * - single element: X (digit) or port name (COM1, /dev/ttyS0, ...) * - range list: X-Y * - multiple elements (coma separated): /dev/ttyS0,/dev/ttyUSB0 */ if ( (list_sep_ptr = strchr(range, '-')) != NULL ) { tok = strtok_r(range,"-",&saveptr); if( tok[1] != 0 ) { fprintf(stderr,ERR_OUT_OF_BOUND); free(range); return NULL; } start_port = tok[0]; tok = strtok_r(NULL,"-",&saveptr); if( tok != NULL ) { if( tok[1] != 0 ) { fprintf(stderr,ERR_OUT_OF_BOUND); free(range); return NULL; } stop_port = tok[0]; } else { stop_port = start_port; } } else if ( ((list_sep_ptr = strchr(ports_range, ',')) != NULL ) && (is_serial_port_path(ports_range)) ) { tok = strtok_r(range,",",&saveptr); while( tok != NULL ) { ports_list = add_port(ports_list,tok); tok = strtok_r(NULL,",",&saveptr); } } else { /* we have been provided a single port name */ /* it's a full device name */ if( ports_range[1] != 0 ) { ports_list = add_port(ports_list,range); } /* it's device number */ else { start_port = stop_port = ports_range[0]; } } free(range); } if( start_port == 0 && !flag_auto) { return ports_list; } for (cur_device=device_portname;cur_device->name!= NULL;cur_device++) { if( flag_auto ) { start_port = cur_device->auto_start_port; stop_port = cur_device->auto_stop_port; } for( current_port=start_port; current_port <= stop_port; current_port++){ snprintf(str_tmp, sizeof(str_tmp),cur_device->name, current_port); ports_list = add_port(ports_list,str_tmp); } } return ports_list; } nut-2.7.2/tools/nut-scanner/scan_snmp.c0000644000175000017500000004406112301203177014774 00000000000000/* scan_snmp.c: detect NUT supported SNMP devices * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut-scan.h" #ifdef WITH_SNMP #include #include #include #include /* workaround for buggy Net-SNMP config * from drivers/snmp-ups.h */ #ifdef PACKAGE_BUGREPORT #undef PACKAGE_BUGREPORT #endif #ifdef PACKAGE_NAME #undef PACKAGE_NAME #endif #ifdef PACKAGE_VERSION #undef PACKAGE_VERSION #endif #ifdef PACKAGE_STRING #undef PACKAGE_STRING #endif #ifdef PACKAGE_TARNAME #undef PACKAGE_TARNAME #endif #include #include #ifdef HAVE_PTHREAD #include #endif #include "nutscan-snmp.h" /* Address API change */ #ifndef usmAESPrivProtocol #define USMAESPRIVPROTOCOL "usmAES128PrivProtocol" #else #define USMAESPRIVPROTOCOL "usmAESPrivProtocol" #endif #define SysOID ".1.3.6.1.2.1.1.2.0" static nutscan_device_t * dev_ret = NULL; #ifdef HAVE_PTHREAD static pthread_mutex_t dev_mutex; static pthread_t * thread_array = NULL; static int thread_count = 0; #endif long g_usec_timeout ; /* dynamic link library stuff */ static char * libname = "libnetsnmp"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; static void (*nut_init_snmp)(const char *type); static void (*nut_snmp_sess_init)(netsnmp_session * session); static void * (*nut_snmp_sess_open)(struct snmp_session *session); static int (*nut_snmp_sess_close)(void *handle); static struct snmp_session * (*nut_snmp_sess_session)(void *handle); static void * (*nut_snmp_parse_oid)(const char *input, oid *objid, size_t *objidlen); static struct snmp_pdu * (*nut_snmp_pdu_create) (int command ); netsnmp_variable_list * (*nut_snmp_add_null_var)(netsnmp_pdu *pdu, const oid *objid, size_t objidlen); static int (*nut_snmp_sess_synch_response) (void *sessp, netsnmp_pdu *pdu, netsnmp_pdu **response); static int (*nut_snmp_oid_compare) (const oid *in_name1, size_t len1, const oid *in_name2, size_t len2); static void (*nut_snmp_free_pdu) (netsnmp_pdu *pdu); static int (*nut_generate_Ku)(const oid * hashtype, u_int hashtype_len, u_char * P, size_t pplen, u_char * Ku, size_t * kulen); static const char * (*nut_snmp_api_errstring) (int snmp_errnumber); static int (*nut_snmp_errno); static oid * (*nut_usmAESPrivProtocol); static oid * (*nut_usmHMACMD5AuthProtocol); static oid * (*nut_usmHMACSHA1AuthProtocol); static oid * (*nut_usmDESPrivProtocol); /* return 0 on error */ int nutscan_load_snmp_library() { if( dl_handle != NULL ) { /* if previous init failed */ if( dl_handle == (void *)1 ) { return 0; } /* init has already been done */ return 1; } if( lt_dlinit() != 0 ) { fprintf(stderr, "Error initializing lt_init\n"); return 0; } dl_handle = lt_dlopenext(libname); if (!dl_handle) { dl_error = lt_dlerror(); goto err; } lt_dlerror(); /* Clear any existing error */ *(void **) (&nut_init_snmp) = lt_dlsym(dl_handle, "init_snmp"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_init) = lt_dlsym(dl_handle, "snmp_sess_init"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_open) = lt_dlsym(dl_handle, "snmp_sess_open"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_close) = lt_dlsym(dl_handle, "snmp_sess_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_session) = lt_dlsym(dl_handle, "snmp_sess_session"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_parse_oid) = lt_dlsym(dl_handle, "snmp_parse_oid"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_pdu_create) = lt_dlsym(dl_handle, "snmp_pdu_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_add_null_var) = lt_dlsym(dl_handle, "snmp_add_null_var"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_synch_response) = lt_dlsym(dl_handle, "snmp_sess_synch_response"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_oid_compare) = lt_dlsym(dl_handle, "snmp_oid_compare"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_free_pdu) = lt_dlsym(dl_handle,"snmp_free_pdu"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_generate_Ku) = lt_dlsym(dl_handle, "generate_Ku"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_api_errstring) = lt_dlsym(dl_handle, "snmp_api_errstring"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_errno) = lt_dlsym(dl_handle, "snmp_errno"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usmAESPrivProtocol) = lt_dlsym(dl_handle, USMAESPRIVPROTOCOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usmHMACMD5AuthProtocol) = lt_dlsym(dl_handle, "usmHMACMD5AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usmHMACSHA1AuthProtocol) = lt_dlsym(dl_handle, "usmHMACSHA1AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usmDESPrivProtocol) = lt_dlsym(dl_handle, "usmDESPrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } return 1; err: fprintf(stderr, "Cannot load SNMP library (%s) : %s. SNMP search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; } /* end of dynamic link library stuff */ static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response,char * mib) { nutscan_device_t * dev = NULL; struct snmp_session * session; char * buf; session = (*nut_snmp_sess_session)(sec->handle); if(session == NULL) { return; } /* SNMP device found */ dev = nutscan_new_device(); dev->type = TYPE_SNMP; dev->driver = strdup("snmp-ups"); dev->port = strdup(session->peername); buf = malloc( response->variables->val_len + 1 ); if( buf ) { memcpy(buf,response->variables->val.string, response->variables->val_len); buf[response->variables->val_len]=0; nutscan_add_option_to_device(dev,"desc",buf); free(buf); } nutscan_add_option_to_device(dev,"mibs",mib); /* SNMP v3 */ if( session->community == NULL || session->community[0] == 0) { if( sec->secLevel ) { nutscan_add_option_to_device(dev,"secLevel", sec->secLevel); } if( sec->secName ) { nutscan_add_option_to_device(dev,"secName", sec->secName); } if( sec->authPassword ) { nutscan_add_option_to_device(dev,"authPassword", sec->authPassword); } if( sec->privPassword ) { nutscan_add_option_to_device(dev,"privPassword", sec->privPassword); } if( sec->authProtocol ) { nutscan_add_option_to_device(dev,"authProtocol", sec->authProtocol); } if( sec->privProtocol ) { nutscan_add_option_to_device(dev,"privProtocol", sec->privProtocol); } } else { buf = malloc( session->community_len + 1 ); if( buf ) { memcpy(buf,session->community, session->community_len); buf[session->community_len]=0; nutscan_add_option_to_device(dev,"community",buf); free(buf); } } #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif dev_ret = nutscan_add_device_to_device(dev_ret,dev); #ifdef HAVE_PTHREAD pthread_mutex_unlock(&dev_mutex); #endif } static struct snmp_pdu * scan_snmp_get_manufacturer(char* oid_str,void* handle) { size_t name_len; oid name[MAX_OID_LEN]; struct snmp_pdu *pdu, *response = NULL; int status; int index = 0; /* create and send request. */ name_len = MAX_OID_LEN; if (!(*nut_snmp_parse_oid)(oid_str, name, &name_len)) { index++; return NULL; } pdu = (*nut_snmp_pdu_create)(SNMP_MSG_GET); if (pdu == NULL) { index++; return NULL; } (*nut_snmp_add_null_var)(pdu, name, name_len); status = (*nut_snmp_sess_synch_response)(handle,pdu, &response); if( response == NULL ) { index++; return NULL; } if(status!=STAT_SUCCESS||response->errstat!=SNMP_ERR_NOERROR|| response->variables == NULL || response->variables->name == NULL || (*nut_snmp_oid_compare)(response->variables->name, response->variables->name_length, name, name_len) != 0 || response->variables->val.string == NULL ) { (*nut_snmp_free_pdu)(response); index++; return NULL; } return response; } static void try_all_oid(void * arg) { struct snmp_pdu *response = NULL; int index = 0; nutscan_snmp_t * sec = (nutscan_snmp_t *)arg; while(snmp_device_table[index].oid != NULL) { response = scan_snmp_get_manufacturer(snmp_device_table[index].oid,sec->handle); if( response == NULL ) { index++; continue; } scan_snmp_add_device(sec,response,snmp_device_table[index].mib); (*nut_snmp_free_pdu)(response); response = NULL; index++; } } static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec) { (*nut_snmp_sess_init)(snmp_sess); snmp_sess->peername = sec->peername; if( sec->community != NULL || sec->secLevel == NULL ) { snmp_sess->version = SNMP_VERSION_1; if( sec->community != NULL ) { snmp_sess->community = (unsigned char *)sec->community; snmp_sess->community_len = strlen(sec->community); } else { snmp_sess->community = (unsigned char *)"public"; snmp_sess->community_len = strlen("public"); } } else { /* SNMP v3 */ snmp_sess->version = SNMP_VERSION_3; /* Security level */ if (strcmp(sec->secLevel, "noAuthNoPriv") == 0) snmp_sess->securityLevel = SNMP_SEC_LEVEL_NOAUTH; else if (strcmp(sec->secLevel, "authNoPriv") == 0) snmp_sess->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; else if (strcmp(sec->secLevel, "authPriv") == 0) snmp_sess->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; else { fprintf(stderr,"Bad SNMPv3 securityLevel: %s\n", sec->secLevel); return 0; } /* Security name */ if( sec->secName == NULL ) { fprintf(stderr,"securityName is required for SNMPv3\n"); return 0; } snmp_sess->securityName = strdup(sec->secName); snmp_sess->securityNameLen = strlen(snmp_sess->securityName); /* Everything is ready for NOAUTH */ if( snmp_sess->securityLevel == SNMP_SEC_LEVEL_NOAUTH ) { return 1; } /* Process mandatory fields, based on the security level */ switch (snmp_sess->securityLevel) { case SNMP_SEC_LEVEL_AUTHNOPRIV: if (sec->authPassword == NULL) { fprintf(stderr, "authPassword is required for SNMPv3 in %s mode\n", sec->secLevel); return 0; } break; case SNMP_SEC_LEVEL_AUTHPRIV: if ((sec->authPassword == NULL) || (sec->privPassword == NULL)) { fprintf(stderr, "authPassword and privPassword are required for SNMPv3 in %s mode\n", sec->secLevel); return 0; } break; default: /* nothing else needed */ break; } /* Process authentication protocol and key */ snmp_sess->securityAuthKeyLen = USM_AUTH_KU_LEN; /* default to MD5 */ snmp_sess->securityAuthProto = (*nut_usmHMACMD5AuthProtocol); snmp_sess->securityAuthProtoLen = sizeof((*nut_usmHMACMD5AuthProtocol))/ sizeof(oid); if( sec->authProtocol ) { if (strcmp(sec->authProtocol, "SHA") == 0) { snmp_sess->securityAuthProto = (*nut_usmHMACSHA1AuthProtocol); snmp_sess->securityAuthProtoLen = sizeof((*nut_usmHMACSHA1AuthProtocol))/ sizeof(oid); } else { if (strcmp(sec->authProtocol, "MD5") != 0) { fprintf(stderr, "Bad SNMPv3 authProtocol: %s", sec->authProtocol); return 0; } } } /* set the authentication key to a MD5/SHA1 hashed version of * our passphrase (must be at least 8 characters long) */ if ((*nut_generate_Ku)(snmp_sess->securityAuthProto, snmp_sess->securityAuthProtoLen, (u_char *) sec->authPassword, strlen(sec->authPassword), snmp_sess->securityAuthKey, &snmp_sess->securityAuthKeyLen) != SNMPERR_SUCCESS) { fprintf(stderr, "Error generating Ku from authentication pass phrase\n"); return 0; } /* Everything is ready for AUTHNOPRIV */ if( snmp_sess->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV ) { return 1; } /* default to DES */ snmp_sess->securityPrivProto=(*nut_usmDESPrivProtocol); snmp_sess->securityPrivProtoLen = sizeof((*nut_usmDESPrivProtocol))/sizeof(oid); if( sec->privProtocol ) { if (strcmp(sec->privProtocol, "AES") == 0) { snmp_sess->securityPrivProto= (*nut_usmAESPrivProtocol); snmp_sess->securityPrivProtoLen = sizeof((*nut_usmAESPrivProtocol))/ sizeof(oid); } else { if (strcmp(sec->privProtocol, "DES") != 0) { fprintf(stderr, "Bad SNMPv3 authProtocol: %s\n" ,sec->authProtocol); return 0; } } } /* set the private key to a MD5/SHA hashed version of * our passphrase (must be at least 8 characters long) */ snmp_sess->securityPrivKeyLen = USM_PRIV_KU_LEN; if ((*nut_generate_Ku)(snmp_sess->securityAuthProto, snmp_sess->securityAuthProtoLen, (u_char *) sec->privPassword, strlen(sec->privPassword), snmp_sess->securityPrivKey, &snmp_sess->securityPrivKeyLen) != SNMPERR_SUCCESS) { fprintf(stderr, "Error generating Ku from private pass phrase\n"); return 0; } } return 1; } static void * try_SysOID(void * arg) { struct snmp_session snmp_sess; void * handle; struct snmp_pdu *pdu, *response = NULL, *resp = NULL; oid name[MAX_OID_LEN]; size_t name_len = MAX_OID_LEN; nutscan_snmp_t * sec = (nutscan_snmp_t *)arg; int index = 0; int sysoid_found = 0; /* Initialize session */ if( !init_session(&snmp_sess,sec) ) { goto try_SysOID_free; } snmp_sess.retries = 0; snmp_sess.timeout = g_usec_timeout; /* Open the session */ handle = (*nut_snmp_sess_open)(&snmp_sess); /* establish the session */ if (handle == NULL) { fprintf(stderr,"Failed to open SNMP session for %s.\n", sec->peername); goto try_SysOID_free; } /* create and send request. */ if (!(*nut_snmp_parse_oid)(SysOID, name, &name_len)) { fprintf(stderr,"SNMP errors: %s\n", (*nut_snmp_api_errstring)((*nut_snmp_errno))); (*nut_snmp_sess_close)(handle); goto try_SysOID_free; } pdu = (*nut_snmp_pdu_create)(SNMP_MSG_GET); if (pdu == NULL) { fprintf(stderr,"Not enough memory\n"); (*nut_snmp_sess_close)(handle); goto try_SysOID_free; } (*nut_snmp_add_null_var)(pdu, name, name_len); (*nut_snmp_sess_synch_response)(handle, pdu, &response); if (response) { sec->handle = handle; /* SNMP device found */ /* SysOID is supposed to give the required MIB. */ /* Check if the received OID match with a known sysOID */ if(response->variables != NULL && response->variables->val.objid != NULL){ while(snmp_device_table[index].oid != NULL) { if(snmp_device_table[index].sysoid == NULL ) { index++; continue; } name_len = MAX_OID_LEN; if (!(*nut_snmp_parse_oid)( snmp_device_table[index].sysoid, name, &name_len)) { index++; continue; } if ( (*nut_snmp_oid_compare)( response->variables->val.objid, response->variables->val_len/sizeof(oid), name, name_len) == 0 ) { /* we have found a relevent sysoid */ resp = scan_snmp_get_manufacturer( snmp_device_table[index].oid, handle); if( resp != NULL ) { scan_snmp_add_device(sec,resp, snmp_device_table[index].mib); sysoid_found = 1; (*nut_snmp_free_pdu)(resp); } } index++; } } /* try a list of known OID */ if( !sysoid_found ) { try_all_oid(sec); } (*nut_snmp_free_pdu)(response); response = NULL; } (*nut_snmp_sess_close)(handle); try_SysOID_free: if( sec->peername ) { free(sec->peername); } free(sec); return NULL; } nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip,long usec_timeout, nutscan_snmp_t * sec) { int i; nutscan_snmp_t * tmp_sec; nutscan_ip_iter_t ip; char * ip_str = NULL; #ifdef HAVE_PTHREAD pthread_t thread; pthread_mutex_init(&dev_mutex,NULL); #endif if( !nutscan_avail_snmp ) { return NULL; } g_usec_timeout = usec_timeout; /* Initialize the SNMP library */ (*nut_init_snmp)("nut-scanner"); ip_str = nutscan_ip_iter_init(&ip, start_ip, stop_ip); while(ip_str != NULL) { tmp_sec = malloc(sizeof(nutscan_snmp_t)); memcpy(tmp_sec, sec, sizeof(nutscan_snmp_t)); tmp_sec->peername = ip_str; #ifdef HAVE_PTHREAD if (pthread_create(&thread,NULL,try_SysOID,(void*)tmp_sec)==0){ thread_count++; thread_array = realloc(thread_array, thread_count*sizeof(pthread_t)); thread_array[thread_count-1] = thread; } #else try_SysOID((void *)tmp_sec); #endif ip_str = nutscan_ip_iter_inc(&ip); }; #ifdef HAVE_PTHREAD for ( i=0; i < thread_count ; i++) { pthread_join(thread_array[i],NULL); } pthread_mutex_destroy(&dev_mutex); free(thread_array); #endif return nutscan_rewind_device(dev_ret); } #else /* WITH_SNMP */ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip,long usec_timeout, nutscan_snmp_t * sec) { return NULL; } #endif /* WITH_SNMP */ nut-2.7.2/tools/nut-scanner/nutscan-snmp.h0000644000175000017500000000442112324033413015441 00000000000000/* nutscan-snmp * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef DEVSCAN_SNMP_H #define DEVSCAN_SNMP_H typedef struct { char * oid; char * mib; char * sysoid; } snmp_device_id_t; /* SNMP IDs device table */ static snmp_device_id_t snmp_device_table[] = { { ".1.3.6.1.4.1.4555.1.1.1.1.1.1.0" , "netvision", ".1.3.6.1.4.1.4555.1.1.1"}, { ".1.3.6.1.4.1.4779.1.3.5.2.1.24.1" , "baytech", NULL}, { ".1.3.6.1.4.1.318.1.1.1.1.1.1.0" , "apcc", NULL}, { "1.3.6.1.4.1.534.1.1.2.0" , "pw", ".1.3.6.1.4.1.534.1"}, { ".1.3.6.1.4.1.17373.3.1.1.0" , "aphel_genesisII", ".1.3.6.1.4.1.17373"}, { ".1.3.6.1.4.1.534.6.6.6.1.1.12.0" , "aphel_revelation", ".1.3.6.1.4.1.534.6.6.6"}, { ".1.3.6.1.4.1.534.6.6.7.1.2.1.2.0" , "eaton_epdu", ".1.3.6.1.4.1.534.6.6.7"}, { "" , "pulizzi_monitored", NULL}, { ".1.3.6.1.4.1.20677.1" , "pulizzi_switched1", ".1.3.6.1.4.1.20677.1"}, { ".1.3.6.1.4.1.20677.1" , "pulizzi_switched2", ".1.3.6.1.4.1.20677.2"}, { ".1.3.6.1.4.1.2947.1.1.2.0" , "bestpower", NULL}, { ".1.3.6.1.4.1.3808.1.1.1.1.1.1.0" , "cyberpower", ".1.3.6.1.4.1.3808"}, { "" , "xppc", ".1.3.6.1.4.1.935"}, { "" , "delta_ups", ".1.3.6.1.4.1.2254.2.4"}, { ".1.3.6.1.4.1.705.1.1.1.0" , "mge", ".1.3.6.1.4.1.705.1"}, { ".1.3.6.1.4.1.232.165.3.1.1.0" , "cpqpower", ".1.3.6.1.4.1.232.165.3"}, { ".1.3.6.1.4.1.13742.1.1.12.0" , "raritan", ".1.3.6.1.4.1.13742"}, { "1.3.6.1.2.1.33.1.1.1.0" , "ietf", ".1.3.6.1.2.1.33"}, /* Terminating entry */ { NULL, NULL, NULL} }; #endif /* DEVSCAN_SNMP_H */ nut-2.7.2/tools/nut-scanner/scan_nut.c0000644000175000017500000001651412303134466014635 00000000000000/* scan_nut.c: detect remote NUT services * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "upsclient.h" #include "nut-scan.h" #ifdef HAVE_PTHREAD #include #endif #include /* dynamic link library stuff */ static char * libname = "libupsclient"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; static int (*nut_upscli_splitaddr)(const char *buf,char **hostname, int *port); static int (*nut_upscli_tryconnect)(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout); static int (*nut_upscli_list_start)(UPSCONN_t *ups, unsigned int numq, const char **query); static int (*nut_upscli_list_next)(UPSCONN_t *ups, unsigned int numq, const char **query,unsigned int *numa, char ***answer); static int (*nut_upscli_disconnect)(UPSCONN_t *ups); static nutscan_device_t * dev_ret = NULL; #ifdef HAVE_PTHREAD static pthread_mutex_t dev_mutex; #endif struct scan_nut_arg { char * hostname; long timeout; }; /* return 0 on error */ int nutscan_load_upsclient_library() { if( dl_handle != NULL ) { /* if previous init failed */ if( dl_handle == (void *)1 ) { return 0; } /* init has already been done */ return 1; } if( lt_dlinit() != 0 ) { fprintf(stderr, "Error initializing lt_init\n"); return 0; } dl_handle = lt_dlopenext(libname); if (!dl_handle) { dl_error = lt_dlerror(); goto err; } lt_dlerror(); /* Clear any existing error */ *(void **) (&nut_upscli_splitaddr) = lt_dlsym(dl_handle, "upscli_splitaddr"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_tryconnect) = lt_dlsym(dl_handle, "upscli_tryconnect"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_list_start) = lt_dlsym(dl_handle, "upscli_list_start"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_list_next) = lt_dlsym(dl_handle, "upscli_list_next"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_disconnect) = lt_dlsym(dl_handle, "upscli_disconnect"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } return 1; err: fprintf(stderr, "Cannot load NUT library (%s) : %s. NUT search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; } /* FIXME: SSL support */ static void * list_nut_devices(void * arg) { struct scan_nut_arg * nut_arg = (struct scan_nut_arg*)arg; char *target_hostname = nut_arg->hostname; struct timeval tv; int port; unsigned int numq, numa; const char *query[4]; char **answer; char *hostname = NULL; UPSCONN_t *ups = malloc(sizeof(*ups)); nutscan_device_t * dev = NULL; int buf_size; tv.tv_sec = nut_arg->timeout / (1000*1000); tv.tv_usec = nut_arg->timeout % (1000*1000); query[0] = "UPS"; numq = 1; if ((*nut_upscli_splitaddr)(target_hostname, &hostname, &port) != 0) { free(target_hostname); free(nut_arg); free(ups); return NULL; } if ((*nut_upscli_tryconnect)(ups, hostname, port,UPSCLI_CONN_TRYSSL,&tv) < 0) { free(target_hostname); free(nut_arg); free(ups); return NULL; } if((*nut_upscli_list_start)(ups, numq, query) < 0) { (*nut_upscli_disconnect)(ups); free(target_hostname); free(nut_arg); free(ups); return NULL; } while ((*nut_upscli_list_next)(ups,numq, query, &numa, &answer) == 1) { /* UPS */ if (numa < 3) { (*nut_upscli_disconnect)(ups); free(target_hostname); free(nut_arg); free(ups); return NULL; } /* FIXME: check for duplication by getting driver.port and device.serial * for comparison with other busses results */ /* FIXME: * - also print answer[2] if != "Unavailable"? * - for upsmon.conf or ups.conf (using dummy-ups)? */ if (numa >= 3) { dev = nutscan_new_device(); dev->type = TYPE_NUT; dev->driver = strdup("nutclient"); /* +1+1 is for '@' character and terminating 0 */ buf_size = strlen(answer[1])+strlen(hostname)+1+1; dev->port = malloc(buf_size); if( dev->port ) { snprintf(dev->port,buf_size,"%s@%s",answer[1], hostname); #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif dev_ret = nutscan_add_device_to_device(dev_ret,dev); #ifdef HAVE_PTHREAD pthread_mutex_unlock(&dev_mutex); #endif } } } (*nut_upscli_disconnect)(ups); free(target_hostname); free(nut_arg); free(ups); return NULL; } nutscan_device_t * nutscan_scan_nut(const char* startIP, const char* stopIP, const char* port,long usec_timeout) { nutscan_ip_iter_t ip; char * ip_str = NULL; char * ip_dest = NULL; char buf[SMALLBUF]; struct sigaction oldact; int change_action_handler = 0; int i; struct scan_nut_arg *nut_arg; #ifdef HAVE_PTHREAD pthread_t thread; pthread_t * thread_array = NULL; int thread_count = 0; pthread_mutex_init(&dev_mutex,NULL); #endif if( !nutscan_avail_nut ) { return NULL; } /* Ignore SIGPIPE if the caller hasn't set a handler for it yet */ if( sigaction(SIGPIPE, NULL, &oldact) == 0 ) { if( oldact.sa_handler == SIG_DFL ) { change_action_handler = 1; signal(SIGPIPE,SIG_IGN); } } ip_str = nutscan_ip_iter_init(&ip,startIP,stopIP); while( ip_str != NULL ) { if( port ) { if( ip.type == IPv4 ) { snprintf(buf,sizeof(buf),"%s:%s",ip_str,port); } else { snprintf(buf,sizeof(buf),"[%s]:%s",ip_str,port); } ip_dest = strdup(buf); } else { ip_dest = strdup(ip_str); } if((nut_arg = malloc(sizeof(struct scan_nut_arg))) == NULL ) { free(ip_dest); break; } nut_arg->timeout = usec_timeout; nut_arg->hostname = ip_dest; #ifdef HAVE_PTHREAD if (pthread_create(&thread,NULL,list_nut_devices,(void*)nut_arg)==0){ thread_count++; thread_array = realloc(thread_array, thread_count*sizeof(pthread_t)); thread_array[thread_count-1] = thread; } #else list_nut_devices(nut_arg); #endif free(ip_str); ip_str = nutscan_ip_iter_inc(&ip); } #ifdef HAVE_PTHREAD for ( i=0; i < thread_count ; i++) { pthread_join(thread_array[i],NULL); } pthread_mutex_destroy(&dev_mutex); free(thread_array); #endif if(change_action_handler) { signal(SIGPIPE,SIG_DFL); } return nutscan_rewind_device(dev_ret); } nut-2.7.2/tools/nut-scanner/nutscan-ip.h0000644000175000017500000000301712301203177015075 00000000000000/* ip.h: iterator for IPv4 or IPv6 addresses * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SCAN_IP #define SCAN_IP #include #include #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif enum network_type { IPv4, IPv6 }; typedef struct nutscan_ip_iter { enum network_type type; struct in_addr start; struct in_addr stop; struct in6_addr start6; struct in6_addr stop6; } nutscan_ip_iter_t; char * nutscan_ip_iter_init(nutscan_ip_iter_t *, const char * startIP, const char * stopIP); char * nutscan_ip_iter_inc(nutscan_ip_iter_t *); int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip); #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #endif nut-2.7.2/tools/nut-scanner/scan_eaton_serial.c0000644000175000017500000002653612303134466016501 00000000000000/* scan_eaton_serial.c: detect Eaton serial XCP, SHUT and Q1 devices * * Copyright (C) 2012 Arnaud Quette * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" /* Need this on AIX when using xlc to get alloca */ #ifdef _AIX #pragma alloca #endif /* _AIX */ #include #include #include #include #include #include #include "nut-scan.h" #include "serial.h" #include "bcmxcp_io.h" #include "bcmxcp.h" #include "nutscan-serial.h" #ifdef HAVE_PTHREAD #include #endif /* SHUT header */ #define SHUT_SYNC 0x16 #define MAX_TRY 4 /* BCMXCP header */ extern unsigned char AUT[4]; extern struct pw_baud_rate { int rate; int name; } pw_baud_rates[]; /* Local list of found devices */ static nutscan_device_t * dev_ret = NULL; /* Remap some functions to avoid undesired behavior (drivers/main.c) */ char *getval(const char *var) { return NULL; } #ifdef HAVE_PTHREAD static pthread_mutex_t dev_mutex; #endif /* Drivers name */ #define SHUT_DRIVER_NAME "mge-shut" #define XCP_DRIVER_NAME "bcmxcp" #define Q1_DRIVER_NAME "blazer_ser" /* Fake driver main, for using serial functions, needed for bcmxcp_ser.c */ char *device_path; int upsfd; int exit_flag = 0; int do_lock_port; /* Functions extracted from drivers/bcmxcp.c, to avoid pulling too many things * lightweight function to calculate the 8-bit * two's complement checksum of buf, using XCP data length (including header) * the result must be 0 for the sequence data to be valid */ int checksum_test(const unsigned char *buf) { unsigned char checksum = 0; int i, length; /* buf[2] is the length of the XCP frame ; add 5 for the header */ length = (int)(buf[2]) + 5; for (i = 0; i < length; i++) { checksum += buf[i]; } /* Compute the 8-bit, Two's Complement checksum now and return it */ checksum = ((0x100 - checksum) & 0xFF); return (checksum == 0); } unsigned char calc_checksum(const unsigned char *buf) { unsigned char c; int i; c = 0; for(i = 0; i < 2 + buf[1]; i++) c -= buf[i]; return c; } /******************************************************************************* * SHUT functions (MGE legacy, but Eaton path forward) ******************************************************************************/ /* Light version of of drivers/libshut.c->shut_synchronise() * return 1 if OK, 0 otherwise */ int shut_synchronise(int upsfd) { int try; u_char reply = '\0'; /* Sync with the UPS according to notification */ for (try = 0; try < MAX_TRY; try++) { if ((ser_send_char(upsfd, SHUT_SYNC)) == -1) { continue; } ser_get_char(upsfd, &reply, 1, 0); if (reply == SHUT_SYNC) { return 1; } } return 0; } /* SHUT scan: * send SYNC token (0x16) and receive the SYNC token back * FIXME: maybe try to get device descriptor?! */ nutscan_device_t * nutscan_scan_eaton_serial_shut(const char* port_name) { nutscan_device_t * dev = NULL; int devfd = -1; if ( (devfd = ser_open_nf(port_name)) != -1 ) { /* set RTS to off and DTR to on to allow correct behavior * with UPS using PnP feature */ if (ser_set_dtr(devfd, 1) != -1) { ser_set_rts(devfd, 0); ser_set_speed_nf(devfd, port_name, B2400); if (shut_synchronise(devfd)) { /* Communication established successfully! */ dev = nutscan_new_device(); dev->type = TYPE_EATON_SERIAL; dev->driver = strdup(SHUT_DRIVER_NAME); dev->port = strdup(port_name); #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif dev_ret = nutscan_add_device_to_device(dev_ret, dev); #ifdef HAVE_PTHREAD pthread_mutex_unlock(&dev_mutex); #endif } } /* Close the device */ ser_close(devfd, NULL); } return dev; } /******************************************************************************* * XCP functions (Eaton Powerware legacy) ******************************************************************************/ /* XCP scan: * baudrate nego (...) * Send ESC to take it out of menu * Wait 90ms * Send auth command (AUTHOR[4] = {0xCF, 0x69, 0xE8, 0xD5};) * Wait 500ms (or less?) * Send PW_SET_REQ_ONLY_MODE command (0xA0) and wait for response * [Get ID Block (PW_ID_BLOCK_REQ) (0x31)] */ nutscan_device_t * nutscan_scan_eaton_serial_xcp(const char* port_name) { nutscan_device_t * dev = NULL; int i, ret, devfd = -1; unsigned char answer[256]; unsigned char sbuf[128]; memset(sbuf, 0, 128); if ( (devfd = ser_open_nf(port_name)) != -1 ) { #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif upsfd = devfd; #ifdef HAVE_PTHREAD pthread_mutex_unlock(&dev_mutex); #endif for (i=0; (pw_baud_rates[i].rate != 0) && (dev == NULL); i++) { memset(answer, 0, 256); if (ser_set_speed_nf(devfd, port_name, pw_baud_rates[i].rate) == -1) break; ret = ser_send_char(devfd, 0x1d); /* send ESC to take it out of menu */ if (ret <= 0) break; usleep(90000); send_write_command(AUT, 4); usleep(500000); /* Discovery with Baud Hunting (XCP protocol spec. §4.1.2) * sending PW_SET_REQ_ONLY_MODE should be enough, since * the unit should send back Identification block */ sbuf[0] = PW_COMMAND_START_BYTE; sbuf[1] = (unsigned char)1; sbuf[2] = PW_SET_REQ_ONLY_MODE; sbuf[3] = calc_checksum(sbuf); ret = ser_send_buf_pace(devfd, 1000, sbuf, 4); /* Read PW_COMMAND_START_BYTE byte */ ret = ser_get_char(devfd, answer, 1, 0); #if 0 /* FIXME: seems not needed, but requires testing with more devices! */ if (ret <= 0) { usleep(250000); /* 500000? */ memset(answer, 0, 256); ret = command_sequence(&id_command, 1, answer); } #endif if ( (ret > 0) && (answer[0] == PW_COMMAND_START_BYTE) ) { dev = nutscan_new_device(); dev->type = TYPE_EATON_SERIAL; dev->driver = strdup(XCP_DRIVER_NAME); dev->port = strdup(port_name); #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif dev_ret = nutscan_add_device_to_device(dev_ret, dev); #ifdef HAVE_PTHREAD pthread_mutex_unlock(&dev_mutex); #endif break; } usleep(100000); } /* Close the device */ ser_close(devfd, NULL); } return dev; } /******************************************************************************* * Q1 functions (Phoenixtec/Centralion/Santak, still Eaton path forward) ******************************************************************************/ #define SER_WAIT_SEC 1 /* 3 seconds for Best UPS */ #define MAXTRIES 3 /* Q1 scan: * - open the serial port and set the speed to 2400 baud * - simply try to get Q1 (status) string * - check its size and first char. which should be '(' */ nutscan_device_t * nutscan_scan_eaton_serial_q1(const char* port_name) { nutscan_device_t * dev = NULL; struct termios tio; int ret = 0, retry; int devfd = -1; char buf[128]; if ( (devfd = ser_open_nf(port_name)) != -1 ) { if (ser_set_speed_nf(devfd, port_name, B2400) != -1) { if (!tcgetattr(devfd, &tio)) { /* Use canonical mode input processing (to read reply line) */ tio.c_lflag |= ICANON; /* Canonical input (erase and kill processing) */ tio.c_cc[VEOF] = _POSIX_VDISABLE; tio.c_cc[VEOL] = '\r'; tio.c_cc[VERASE] = _POSIX_VDISABLE; tio.c_cc[VINTR] = _POSIX_VDISABLE; tio.c_cc[VKILL] = _POSIX_VDISABLE; tio.c_cc[VQUIT] = _POSIX_VDISABLE; tio.c_cc[VSUSP] = _POSIX_VDISABLE; tio.c_cc[VSTART] = _POSIX_VDISABLE; tio.c_cc[VSTOP] = _POSIX_VDISABLE; if (!tcsetattr(devfd, TCSANOW, &tio)) { /* Set the default (normal) cablepower */ ser_set_dtr(devfd, 1); ser_set_rts(devfd, 0); /* Allow some time to settle for the cablepower */ usleep(100000); /* Only try pure 'Q1', not older ones like 'D' or 'QS' * > [Q1\r] * < [(226.0 195.0 226.0 014 49.0 27.5 30.0 00001000\r] */ for (retry = 1; retry <= MAXTRIES; retry++) { /* simplified code */ ser_flush_io(devfd); if ( (ret = ser_send(devfd, "Q1\r")) > 0) { /* Get Q1 reply */ if ( (ret = ser_get_buf(devfd, buf, sizeof(buf), SER_WAIT_SEC, 0)) > 0) { /* Check answer */ /* should at least (and most) be 46 chars */ if (ret >= 46) { if (buf[0] == '(') { dev = nutscan_new_device(); dev->type = TYPE_EATON_SERIAL; dev->driver = strdup(Q1_DRIVER_NAME); dev->port = strdup(port_name); #ifdef HAVE_PTHREAD pthread_mutex_lock(&dev_mutex); #endif dev_ret = nutscan_add_device_to_device(dev_ret, dev); #ifdef HAVE_PTHREAD pthread_mutex_unlock(&dev_mutex); #endif break; } } } } } } } } /* Close the device */ ser_close(devfd, NULL); } return dev; } static void * nutscan_scan_eaton_serial_device(void * port_arg) { nutscan_device_t * dev = NULL; char* port_name = (char*) port_arg; /* Try SHUT first */ if ( (dev = nutscan_scan_eaton_serial_shut(port_name)) == NULL) { usleep(100000); /* Else, try XCP */ if ( (dev = nutscan_scan_eaton_serial_xcp(port_name)) == NULL) { /* Else, try Q1 */ usleep(100000); dev = nutscan_scan_eaton_serial_q1(port_name); } /* Else try UTalk? */ } return dev; } nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_range) { struct sigaction oldact; int change_action_handler = 0; char *current_port_name = NULL; char **serial_ports_list; int current_port_nb; int i; #ifdef HAVE_PTHREAD pthread_t thread; pthread_t * thread_array = NULL; int thread_count = 0; pthread_mutex_init(&dev_mutex,NULL); #endif /* 1) Get ports_list */ serial_ports_list = nutscan_get_serial_ports_list(ports_range); if( serial_ports_list == NULL ) { return NULL; } /* Ignore SIGPIPE if the caller hasn't set a handler for it yet */ if( sigaction(SIGPIPE, NULL, &oldact) == 0 ) { if( oldact.sa_handler == SIG_DFL ) { change_action_handler = 1; signal(SIGPIPE,SIG_IGN); } } /* port(s) iterator */ current_port_nb = 0; while(serial_ports_list[current_port_nb] != NULL) { current_port_name = serial_ports_list[current_port_nb]; #ifdef HAVE_PTHREAD if (pthread_create(&thread, NULL, nutscan_scan_eaton_serial_device, (void*)current_port_name) == 0){ thread_count++; thread_array = realloc(thread_array, thread_count*sizeof(pthread_t)); thread_array[thread_count-1] = thread; } #else nutscan_scan_eaton_serial_device(current_port_name); #endif current_port_nb++; } #ifdef HAVE_PTHREAD for ( i = 0; i < thread_count ; i++) { pthread_join(thread_array[i],NULL); } pthread_mutex_destroy(&dev_mutex); free(thread_array); #endif if(change_action_handler) { signal(SIGPIPE,SIG_DFL); } /* free everything... */ i=0; while(serial_ports_list[i] != NULL) { free(serial_ports_list[i]); i++; } free( serial_ports_list); return nutscan_rewind_device(dev_ret); } nut-2.7.2/tools/nut-scanner/scan_usb.c0000644000175000017500000001625612303134466014623 00000000000000/* scan_usb.c: detect NUT supported USB devices * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut-scan.h" #ifdef WITH_USB #include "upsclient.h" #include "nutscan-usb.h" #include #include #include /* dynamic link library stuff */ static char * libname = "libusb"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; static int (*nut_usb_close)(usb_dev_handle *dev); static int (*nut_usb_find_busses)(void); static char * (*nut_usb_strerror)(void); static void (*nut_usb_init)(void); static int (*nut_usb_get_string_simple)(usb_dev_handle *dev, int index, char *buf, size_t buflen); static struct usb_bus * (*nut_usb_busses); static usb_dev_handle * (*nut_usb_open)(struct usb_device *dev); static int (*nut_usb_find_devices)(void); /* return 0 on error */ int nutscan_load_usb_library() { if( dl_handle != NULL ) { /* if previous init failed */ if( dl_handle == (void *)1 ) { return 0; } /* init has already been done */ return 1; } if( lt_dlinit() != 0 ) { fprintf(stderr, "Error initializing lt_init\n"); return 0; } dl_handle = lt_dlopenext(libname); if (!dl_handle) { dl_error = lt_dlerror(); goto err; } lt_dlerror(); /* Clear any existing error */ *(void **) (&nut_usb_close) = lt_dlsym(dl_handle, "usb_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_find_busses) = lt_dlsym(dl_handle, "usb_find_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_strerror) = lt_dlsym(dl_handle, "usb_strerror"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_init) = lt_dlsym(dl_handle, "usb_init"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_string_simple) = lt_dlsym(dl_handle, "usb_get_string_simple"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_busses) = lt_dlsym(dl_handle, "usb_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_open) = lt_dlsym(dl_handle, "usb_open"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **)(&nut_usb_find_devices) = lt_dlsym(dl_handle,"usb_find_devices"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } return 1; err: fprintf(stderr, "Cannot load USB library (%s) : %s. USB search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; } /* end of dynamic link library stuff */ static char* is_usb_device_supported(usb_device_id_t *usb_device_id_list, int dev_VendorID, int dev_ProductID) { usb_device_id_t *usbdev; for (usbdev=usb_device_id_list; usbdev->driver_name != NULL; usbdev++) { if ( (usbdev->vendorID == dev_VendorID) && (usbdev->productID == dev_ProductID) ) { return usbdev->driver_name; } } return NULL; } /* return NULL if error */ nutscan_device_t * nutscan_scan_usb() { int ret; char string[256]; char *driver_name = NULL; char *serialnumber = NULL; char *device_name = NULL; char *vendor_name = NULL; struct usb_device *dev; struct usb_bus *bus; usb_dev_handle *udev; nutscan_device_t * nut_dev = NULL; nutscan_device_t * current_nut_dev = NULL; if( !nutscan_avail_usb ) { return NULL; } /* libusb base init */ (*nut_usb_init)(); (*nut_usb_find_busses)(); (*nut_usb_find_devices)(); for (bus = (*nut_usb_busses); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { if ((driver_name = is_usb_device_supported(usb_device_table, dev->descriptor.idVendor, dev->descriptor.idProduct)) != NULL) { /* open the device */ udev = (*nut_usb_open)(dev); if (!udev) { fprintf(stderr,"Failed to open device, \ skipping. (%s)\n", (*nut_usb_strerror)()); continue; } /* get serial number */ if (dev->descriptor.iSerialNumber) { ret = (*nut_usb_get_string_simple)(udev, dev->descriptor.iSerialNumber, string, sizeof(string)); if (ret > 0) { serialnumber = strdup(rtrim(string, ' ')); } } /* get product name */ if (dev->descriptor.iProduct) { ret = (*nut_usb_get_string_simple)(udev, dev->descriptor.iProduct, string, sizeof(string)); if (ret > 0) { device_name = strdup(rtrim(string, ' ')); } } /* get vendor name */ if (dev->descriptor.iManufacturer) { ret = (*nut_usb_get_string_simple)(udev, dev->descriptor.iManufacturer, string, sizeof(string)); if (ret > 0) { vendor_name = strdup(rtrim(string, ' ')); } } nut_dev = nutscan_new_device(); if(nut_dev == NULL) { fprintf(stderr,"Memory allocation \ error\n"); nutscan_free_device(current_nut_dev); free(serialnumber); free(device_name); free(vendor_name); return NULL; } nut_dev->type = TYPE_USB; if(driver_name) { nut_dev->driver = strdup(driver_name); } nut_dev->port = strdup("auto"); sprintf(string,"%04X",dev->descriptor.idVendor); nutscan_add_option_to_device(nut_dev,"vendorid", string); sprintf(string,"%04X", dev->descriptor.idProduct); nutscan_add_option_to_device(nut_dev,"productid", string); if(device_name) { nutscan_add_option_to_device(nut_dev, "product", device_name); free(device_name); } if(serialnumber) { nutscan_add_option_to_device(nut_dev, "serial", serialnumber); free(serialnumber); } if(vendor_name) { nutscan_add_option_to_device(nut_dev, "vendor", vendor_name); free(vendor_name); } nutscan_add_option_to_device(nut_dev,"bus", bus->dirname); current_nut_dev = nutscan_add_device_to_device( current_nut_dev, nut_dev); memset (string, 0, sizeof(string)); (*nut_usb_close)(udev); } } } return nutscan_rewind_device(current_nut_dev); } #else /* WITH_USB */ nutscan_device_t * nutscan_scan_usb() { return NULL; } #endif /* WITH_USB */ nut-2.7.2/tools/nut-scanner/nutscan-usb.h0000644000175000017500000001040312324033415015254 00000000000000/* nutscan-usb * Copyright (C) 2011 - Arnaud Quette * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef DEVSCAN_USB_H #define DEVSCAN_USB_H #include #include "nut_stdint.h" /* for uint16_t */ typedef struct { uint16_t vendorID; uint16_t productID; char* driver_name; } usb_device_id_t; /* USB IDs device table */ static usb_device_id_t usb_device_table[] = { { 0x0001, 0x0000, "nutdrv_atcl_usb" }, { 0x03f0, 0x0001, "usbhid-ups" }, { 0x03f0, 0x1f01, "bcmxcp_usb" }, { 0x03f0, 0x1f02, "bcmxcp_usb" }, { 0x03f0, 0x1f06, "usbhid-ups" }, { 0x03f0, 0x1f08, "usbhid-ups" }, { 0x03f0, 0x1f09, "usbhid-ups" }, { 0x03f0, 0x1f0a, "usbhid-ups" }, { 0x03f0, 0x1fe0, "usbhid-ups" }, { 0x03f0, 0x1fe1, "usbhid-ups" }, { 0x03f0, 0x1fe2, "usbhid-ups" }, { 0x03f0, 0x1fe3, "usbhid-ups" }, { 0x03f0, 0x1fe5, "usbhid-ups" }, { 0x03f0, 0x1fe6, "usbhid-ups" }, { 0x03f0, 0x1fe7, "usbhid-ups" }, { 0x03f0, 0x1fe8, "usbhid-ups" }, { 0x0463, 0x0001, "usbhid-ups" }, { 0x0463, 0xffff, "usbhid-ups" }, { 0x047c, 0xffff, "usbhid-ups" }, { 0x04b4, 0x5500, "riello_usb" }, { 0x04d8, 0xd004, "usbhid-ups" }, { 0x050d, 0x0375, "usbhid-ups" }, { 0x050d, 0x0551, "usbhid-ups" }, { 0x050d, 0x0750, "usbhid-ups" }, { 0x050d, 0x0751, "usbhid-ups" }, { 0x050d, 0x0900, "usbhid-ups" }, { 0x050d, 0x0910, "usbhid-ups" }, { 0x050d, 0x0912, "usbhid-ups" }, { 0x050d, 0x0980, "usbhid-ups" }, { 0x050d, 0x1100, "usbhid-ups" }, { 0x051d, 0x0002, "usbhid-ups" }, { 0x051d, 0x0003, "usbhid-ups" }, { 0x0592, 0x0002, "bcmxcp_usb" }, { 0x0592, 0x0004, "usbhid-ups" }, { 0x05b8, 0x0000, "blazer_usb" }, { 0x0665, 0x5161, "blazer_usb" }, { 0x06da, 0x0002, "blazer_usb" }, { 0x06da, 0x0003, "blazer_usb" }, { 0x06da, 0x0004, "blazer_usb" }, { 0x06da, 0x0005, "blazer_usb" }, { 0x06da, 0x0201, "blazer_usb" }, { 0x06da, 0x0601, "blazer_usb" }, { 0x06da, 0xffff, "usbhid-ups" }, { 0x075d, 0x0300, "usbhid-ups" }, { 0x0764, 0x0005, "usbhid-ups" }, { 0x0764, 0x0501, "usbhid-ups" }, { 0x0764, 0x0601, "usbhid-ups" }, { 0x0925, 0x1234, "richcomm_usb" }, { 0x09ae, 0x0001, "tripplite_usb" }, { 0x09ae, 0x1003, "usbhid-ups" }, { 0x09ae, 0x1007, "usbhid-ups" }, { 0x09ae, 0x1008, "usbhid-ups" }, { 0x09ae, 0x1009, "usbhid-ups" }, { 0x09ae, 0x1010, "usbhid-ups" }, { 0x09ae, 0x2005, "usbhid-ups" }, { 0x09ae, 0x2007, "usbhid-ups" }, { 0x09ae, 0x2008, "usbhid-ups" }, { 0x09ae, 0x2009, "usbhid-ups" }, { 0x09ae, 0x2010, "usbhid-ups" }, { 0x09ae, 0x2011, "usbhid-ups" }, { 0x09ae, 0x2012, "usbhid-ups" }, { 0x09ae, 0x2013, "usbhid-ups" }, { 0x09ae, 0x2014, "usbhid-ups" }, { 0x09ae, 0x3008, "usbhid-ups" }, { 0x09ae, 0x3009, "usbhid-ups" }, { 0x09ae, 0x3010, "usbhid-ups" }, { 0x09ae, 0x3011, "usbhid-ups" }, { 0x09ae, 0x3012, "usbhid-ups" }, { 0x09ae, 0x3013, "usbhid-ups" }, { 0x09ae, 0x3014, "usbhid-ups" }, { 0x09ae, 0x3015, "usbhid-ups" }, { 0x09ae, 0x3016, "usbhid-ups" }, { 0x09ae, 0x4001, "usbhid-ups" }, { 0x09ae, 0x4002, "usbhid-ups" }, { 0x09ae, 0x4003, "usbhid-ups" }, { 0x09ae, 0x4004, "usbhid-ups" }, { 0x09ae, 0x4005, "usbhid-ups" }, { 0x09ae, 0x4006, "usbhid-ups" }, { 0x09ae, 0x4007, "usbhid-ups" }, { 0x09ae, 0x4008, "usbhid-ups" }, { 0x0d9f, 0x0004, "usbhid-ups" }, { 0x0d9f, 0x00a2, "usbhid-ups" }, { 0x0d9f, 0x00a3, "usbhid-ups" }, { 0x0d9f, 0x00a4, "usbhid-ups" }, { 0x0d9f, 0x00a5, "usbhid-ups" }, { 0x0d9f, 0x00a6, "usbhid-ups" }, { 0x0f03, 0x0001, "blazer_usb" }, { 0x10af, 0x0001, "usbhid-ups" }, { 0x10af, 0x0004, "usbhid-ups" }, { 0x14f0, 0x00c9, "blazer_usb" }, { 0xffff, 0x0000, "blazer_usb" }, /* Terminating entry */ { -1, -1, NULL } }; #endif /* DEVSCAN_USB_H */ nut-2.7.2/tools/nut-scanner/nutscan-device.c0000644000175000017500000000740012277355125015734 00000000000000/* device.c: manipulation of a container describing a NUT device * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "nutscan-device.h" #include #include #include const char * nutscan_device_type_strings[TYPE_END - 1] = { "USB", "SNMP", "XML", "NUT", "IPMI", "Avahi", "serial", }; nutscan_device_t * nutscan_new_device() { nutscan_device_t * device; device = malloc(sizeof(nutscan_device_t)); if( device==NULL) { return NULL; } memset(device,0,sizeof(nutscan_device_t)); return device; } static void deep_free_device(nutscan_device_t * device) { nutscan_options_t * current; if(device==NULL) { return; } if(device->driver) { free(device->driver); } if(device->port) { free(device->port); } while (device->opt != NULL) { current = device->opt; device->opt = current->next; if(current->option != NULL) { free(current->option); } if(current->value != NULL) { free(current->value); } free(current); }; if(device->prev) { device->prev->next = device->next; } if(device->next) { device->next->prev = device->prev; } free(device); } void nutscan_free_device(nutscan_device_t * device) { if(device==NULL) { return; } while(device->prev != NULL) { deep_free_device(device->prev); } while(device->next != NULL) { deep_free_device(device->next); } deep_free_device(device); } void nutscan_add_option_to_device(nutscan_device_t * device, char * option, char * value) { nutscan_options_t **opt; /* search for last entry */ opt = &device->opt; while (NULL != *opt) opt = &(*opt)->next; *opt = (nutscan_options_t *)malloc(sizeof(nutscan_options_t)); // TBD: A gracefull way to propagate memory failure would be nice assert(NULL != *opt); memset(*opt, 0, sizeof(nutscan_options_t)); if( option != NULL ) { (*opt)->option = strdup(option); } else { (*opt)->option = NULL; } if( value != NULL ) { (*opt)->value = strdup(value); } else { (*opt)->value = NULL; } } nutscan_device_t * nutscan_add_device_to_device(nutscan_device_t * first, nutscan_device_t * second) { nutscan_device_t * dev1=NULL; nutscan_device_t * dev2=NULL; /* Get end of first device */ if( first != NULL) { dev1 = first; while(dev1->next != NULL) { dev1 = dev1->next; } } else { if( second == NULL ) { return NULL; } /* return end of second */ dev2 = second; while(dev2->next != NULL) { dev2 = dev2->next; } return dev2; } /* Get start of second */ if( second != NULL ) { dev2 = second; while(dev2->prev != NULL) { dev2 = dev2->prev; } } else { /* return end of first */ dev1 = first; while(dev1->next != NULL) { dev1 = dev1->next; } return dev1; } /* join both */ dev1->next = dev2; dev2->prev = dev1; /* return end of both */ while(dev2->next != NULL) { dev2 = dev2->next; } return dev2; } nutscan_device_t * nutscan_rewind_device(nutscan_device_t * device) { if (NULL == device) return NULL; while (NULL != device->prev) device = device->prev; return device; } nut-2.7.2/tools/nut-scanner/nutscan-ip.c0000644000175000017500000002031312301203177015066 00000000000000/* ip.c: iterator for IPv4 or IPv6 addresses * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "nutscan-ip.h" #include #include "common.h" #include #include #include static void increment_IPv6(struct in6_addr * addr) { int i; for( i=15 ; i>= 0 ; i--) { addr->s6_addr[i]++; if( addr->s6_addr[i] != 0) { break; } } } static void invert_IPv6(struct in6_addr * addr1, struct in6_addr * addr2) { struct in6_addr addr; memcpy(addr.s6_addr,addr1->s6_addr,sizeof(addr.s6_addr)); memcpy(addr1->s6_addr,addr2->s6_addr,sizeof(addr.s6_addr)); memcpy(addr2->s6_addr,addr.s6_addr,sizeof(addr.s6_addr)); } static int ntop( struct in_addr * ip, char * host, size_t host_size) { struct sockaddr_in in; memset(&in,0,sizeof(struct sockaddr_in)); in.sin_addr = *ip; in.sin_family = AF_INET; return getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), host,host_size,NULL,0,NI_NUMERICHOST); } static int ntop6( struct in6_addr * ip, char * host, size_t host_size) { struct sockaddr_in6 in6; memset(&in6,0,sizeof(struct sockaddr_in6)); memcpy( &in6.sin6_addr, ip, sizeof(struct in6_addr) ); in6.sin6_family = AF_INET6; return getnameinfo((struct sockaddr *)&in6, sizeof(struct sockaddr_in6), host,host_size,NULL,0,NI_NUMERICHOST); } /* Return the first ip or NULL if error */ char * nutscan_ip_iter_init(nutscan_ip_iter_t * ip, const char * startIP, const char * stopIP) { int addr; int i; struct addrinfo hints; struct addrinfo *res; struct sockaddr_in * s_in; struct sockaddr_in6 * s_in6; char host[SMALLBUF]; if( startIP == NULL ) { return NULL; } if(stopIP == NULL ) { stopIP = startIP; } memset(&hints,0,sizeof(struct addrinfo)); hints.ai_family = AF_INET; ip->type = IPv4; /* Detecting IPv4 vs IPv6 */ if(getaddrinfo(startIP,NULL,&hints,&res) != 0) { /*Try IPv6 detection */ ip->type = IPv6; hints.ai_family = AF_INET6; if(getaddrinfo(startIP,NULL,&hints,&res) != 0) { fprintf(stderr,"Invalid address : %s\n",startIP); return NULL; } s_in6 = (struct sockaddr_in6 *)res->ai_addr; memcpy(&ip->start6,&s_in6->sin6_addr,sizeof(struct in6_addr)); freeaddrinfo(res); } else { s_in = (struct sockaddr_in *)res->ai_addr; ip->start = s_in->sin_addr; freeaddrinfo(res); } /* Compute stop IP */ if( ip->type == IPv4 ) { hints.ai_family = AF_INET; if(getaddrinfo(stopIP,NULL,&hints,&res) != 0) { fprintf(stderr,"Invalid address : %s\n",stopIP); return NULL; } s_in = (struct sockaddr_in *)res->ai_addr; ip->stop = s_in->sin_addr; freeaddrinfo(res); } else { hints.ai_family = AF_INET6; if(getaddrinfo(stopIP,NULL,&hints,&res) != 0) { fprintf(stderr,"Invalid address : %s\n",stopIP); return NULL; } s_in6 = (struct sockaddr_in6 *)res->ai_addr; memcpy(&ip->stop6,&s_in6->sin6_addr,sizeof(struct in6_addr)); freeaddrinfo(res); } /* Make sure start IP is lesser than stop IP */ if( ip->type == IPv4 ) { if( ntohl(ip->start.s_addr) > ntohl(ip->stop.s_addr) ) { addr = ip->start.s_addr; ip->start.s_addr = ip->stop.s_addr; ip->stop.s_addr = addr; } if( ntop(&ip->start, host, sizeof(host)) != 0 ) { return NULL; } return strdup(host); } else { /* IPv6 */ for( i=0; i<16; i++ ) { if( ip->start6.s6_addr[i] !=ip->stop6.s6_addr[i] ) { if(ip->start6.s6_addr[i]>ip->stop6.s6_addr[i]){ invert_IPv6(&ip->start6,&ip->stop6); } break; } } if( ntop6(&ip->start6, host, sizeof(host)) != 0 ) { return NULL; } return strdup(host); } } /* return the next IP return NULL if there is no more IP */ char * nutscan_ip_iter_inc(nutscan_ip_iter_t * ip) { char host[SMALLBUF]; if( ip->type == IPv4 ) { /* Check if this is the last address to scan */ if(ip->start.s_addr == ip->stop.s_addr) { return NULL; } /* increment the address (need to pass address in host byte order, then pass back in network byte order */ ip->start.s_addr = htonl((ntohl(ip->start.s_addr)+1)); if( ntop(&ip->start, host, sizeof(host)) != 0 ) { return NULL; } return strdup(host); } else { /* Check if this is the last address to scan */ if( memcmp(&ip->start6.s6_addr, &ip->stop6.s6_addr, sizeof(ip->start6.s6_addr)) == 0 ) { return NULL; } increment_IPv6(&ip->start6); if( ntop6(&ip->start6, host, sizeof(host)) != 0 ) { return NULL; } return strdup(host); } } int nutscan_cidr_to_ip(const char * cidr, char ** start_ip, char ** stop_ip) { char * cidr_tok; char * first_ip; char * mask; char * saveptr = NULL; nutscan_ip_iter_t ip; int mask_val; int mask_byte; unsigned long mask_bit; char host[SMALLBUF]; struct addrinfo hints; struct addrinfo *res; struct sockaddr_in * s_in; struct sockaddr_in6 * s_in6; *start_ip = NULL; *stop_ip = NULL; cidr_tok = strdup(cidr); first_ip = strdup(strtok_r(cidr_tok,"/",&saveptr)); if( first_ip == NULL) { return 0; } mask = strtok_r(NULL,"/",&saveptr); if( mask == NULL ) { return 0; } free(cidr_tok); mask_val = atoi(mask); /* Detecting IPv4 vs IPv6 */ memset(&hints,0,sizeof(struct addrinfo)); hints.ai_family = AF_INET; ip.type = IPv4; /* Detecting IPv4 vs IPv6 */ if(getaddrinfo(first_ip,NULL,&hints,&res) != 0) { /*Try IPv6 detection */ ip.type = IPv6; hints.ai_family = AF_INET6; int ret; if((ret=getaddrinfo(first_ip,NULL,&hints,&res)) != 0) { free(first_ip); return 0; } s_in6 = (struct sockaddr_in6 *)res->ai_addr; memcpy(&ip.start6,&s_in6->sin6_addr,sizeof(struct in6_addr)); freeaddrinfo(res); } else { s_in = (struct sockaddr_in *)res->ai_addr; ip.start = s_in->sin_addr; freeaddrinfo(res); } if( ip.type == IPv4 ) { if( mask_val > 0 ) { mask_val --; mask_bit = 0x80000000; mask_bit >>= mask_val; mask_bit--; } else { mask_bit = 0xffffffff; } ip.stop.s_addr = htonl(ntohl(ip.start.s_addr)|mask_bit); ip.start.s_addr = htonl(ntohl(ip.start.s_addr)&(~mask_bit)); if( ntop(&ip.start, host, sizeof(host)) != 0 ) { *start_ip = NULL; *stop_ip = NULL; return 0; } *start_ip = strdup(host); if( ntop(&ip.stop, host, sizeof(host)) != 0 ) { free(*start_ip); *start_ip = NULL; *stop_ip = NULL; return 0; } *stop_ip = strdup(host); free(first_ip); return 1; } else { if(getaddrinfo(first_ip,NULL,&hints,&res) != 0) { return 0; } s_in6 = (struct sockaddr_in6 *)res->ai_addr; memcpy(&ip.stop6,&s_in6->sin6_addr,sizeof(struct in6_addr)); freeaddrinfo(res); mask_byte = mask_val / 8; if( mask_byte < 16 ) { memset( &(ip.stop6.s6_addr[mask_byte+1]), 0xFF, 15 - mask_byte); memset( &(ip.start6.s6_addr[mask_byte+1]), 0x00, 15 - mask_byte); mask_bit = (0x100 >> mask_val%8)-1; ip.stop6.s6_addr[mask_byte] |= mask_bit; ip.start6.s6_addr[mask_byte] &= (~mask_bit); } if( ntop6(&ip.start6, host, sizeof(host)) != 0 ) { *start_ip = NULL; *stop_ip = NULL; return 0; } *start_ip = strdup(host); if( ntop6(&ip.stop6, host, sizeof(host)) != 0 ) { free(*start_ip); *start_ip = NULL; *stop_ip = NULL; return 0; } *stop_ip = strdup(host); } free(first_ip); return 1; } nut-2.7.2/tools/nut-scanner/Makefile.in0000644000175000017500000013214212324034370014714 00000000000000# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @WITH_LIBLTDL_TRUE@bin_PROGRAMS = nut-scanner$(EXEEXT) @WITH_SSL_TRUE@am__append_1 = $(LIBSSL_CFLAGS) @WITH_SSL_TRUE@am__append_2 = $(LIBSSL_LIBS) @WITH_USB_TRUE@am__append_3 = $(LIBUSB_CFLAGS) @WITH_SNMP_TRUE@am__append_4 = $(LIBNETSNMP_CFLAGS) @WITH_NEON_TRUE@am__append_5 = $(LIBNEON_CFLAGS) @WITH_AVAHI_TRUE@am__append_6 = $(LIBAVAHI_CFLAGS) @WITH_IPMI_TRUE@am__append_7 = $(LIBIPMI_CFLAGS) @WITH_DEV_FALSE@am__append_8 = nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h nutscan-serial.h subdir = tools/nut-scanner DIST_COMMON = README $(am__dist_noinst_HEADERS_DIST) \ $(am__include_HEADERS_DIST) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nut_arg_with.m4 \ $(top_srcdir)/m4/nut_check_asciidoc.m4 \ $(top_srcdir)/m4/nut_check_libavahi.m4 \ $(top_srcdir)/m4/nut_check_libfreeipmi.m4 \ $(top_srcdir)/m4/nut_check_libgd.m4 \ $(top_srcdir)/m4/nut_check_libltdl.m4 \ $(top_srcdir)/m4/nut_check_libneon.m4 \ $(top_srcdir)/m4/nut_check_libnetsnmp.m4 \ $(top_srcdir)/m4/nut_check_libnss.m4 \ $(top_srcdir)/m4/nut_check_libopenssl.m4 \ $(top_srcdir)/m4/nut_check_libpowerman.m4 \ $(top_srcdir)/m4/nut_check_libusb.m4 \ $(top_srcdir)/m4/nut_check_libwrap.m4 \ $(top_srcdir)/m4/nut_check_os.m4 \ $(top_srcdir)/m4/nut_report_feature.m4 \ $(top_srcdir)/m4/nut_type_socklen_t.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = @WITH_SSL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) libnutscan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_libnutscan_la_OBJECTS = libnutscan_la-scan_nut.lo \ libnutscan_la-scan_ipmi.lo libnutscan_la-nutscan-device.lo \ libnutscan_la-nutscan-ip.lo libnutscan_la-nutscan-display.lo \ libnutscan_la-nutscan-init.lo libnutscan_la-scan_usb.lo \ libnutscan_la-scan_snmp.lo libnutscan_la-scan_xml_http.lo \ libnutscan_la-scan_avahi.lo libnutscan_la-scan_eaton_serial.lo \ libnutscan_la-nutscan-serial.lo libnutscan_la-serial.lo \ libnutscan_la-bcmxcp_ser.lo libnutscan_la-common.lo libnutscan_la_OBJECTS = $(am_libnutscan_la_OBJECTS) libnutscan_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnutscan_la_CFLAGS) \ $(CFLAGS) $(libnutscan_la_LDFLAGS) $(LDFLAGS) -o $@ @WITH_LIBLTDL_TRUE@am_libnutscan_la_rpath = -rpath $(libdir) PROGRAMS = $(bin_PROGRAMS) am_nut_scanner_OBJECTS = nut_scanner-nut-scanner.$(OBJEXT) nut_scanner_OBJECTS = $(am_nut_scanner_OBJECTS) nut_scanner_DEPENDENCIES = libnutscan.la ../../common/libcommon.la nut_scanner_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(nut_scanner_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libnutscan_la_SOURCES) $(nut_scanner_SOURCES) DIST_SOURCES = $(libnutscan_la_SOURCES) $(nut_scanner_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__dist_noinst_HEADERS_DIST = nutscan-usb.h nutscan-snmp.h nut-scan.h \ nutscan-device.h nutscan-ip.h nutscan-init.h nutscan-serial.h am__include_HEADERS_DIST = nut-scan.h nutscan-device.h nutscan-ip.h \ nutscan-init.h HEADERS = $(dist_noinst_HEADERS) $(include_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) A2X = @A2X@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ ASCIIDOC = @ASCIIDOC@ ASPELL = @ASPELL@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONFPATH = @CONFPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBLATEX = @DBLATEX@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOC_BUILD_LIST = @DOC_BUILD_LIST@ DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@ DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@ DRIVER_MAN_LIST = @DRIVER_MAN_LIST@ DRVPATH = @DRVPATH@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAVAHI_CFLAGS = @LIBAVAHI_CFLAGS@ LIBAVAHI_LIBS = @LIBAVAHI_LIBS@ LIBGD_CFLAGS = @LIBGD_CFLAGS@ LIBGD_LDFLAGS = @LIBGD_LDFLAGS@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@ LIBIPMI_LIBS = @LIBIPMI_LIBS@ LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@ LIBLTDL_LIBS = @LIBLTDL_LIBS@ LIBNEON_CFLAGS = @LIBNEON_CFLAGS@ LIBNEON_LIBS = @LIBNEON_LIBS@ LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@ LIBNETSNMP_LIBS = @LIBNETSNMP_LIBS@ LIBOBJS = @LIBOBJS@ LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@ LIBS = @LIBS@ LIBSSL_CFLAGS = @LIBSSL_CFLAGS@ LIBSSL_LIBS = @LIBSSL_LIBS@ LIBTOOL = @LIBTOOL@ LIBUSB_CFLAGS = @LIBUSB_CFLAGS@ LIBUSB_LIBS = @LIBUSB_LIBS@ LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@ LIBWRAP_LIBS = @LIBWRAP_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NETLIBS = @NETLIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NUT_NETVERSION = @NUT_NETVERSION@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_NAME = @OS_NAME@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIDPATH = @PIDPATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PORT = @PORT@ RANLIB = @RANLIB@ RUN_AS_GROUP = @RUN_AS_GROUP@ RUN_AS_USER = @RUN_AS_USER@ SBINDIR = @SBINDIR@ SED = @SED@ SERLIBS = @SERLIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STATEPATH = @STATEPATH@ STRIP = @STRIP@ SUN_LIBUSB = @SUN_LIBUSB@ TREE_VERSION = @TREE_VERSION@ VERSION = @VERSION@ WORDS_BIGENDIAN = @WORDS_BIGENDIAN@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ cgiexecdir = @cgiexecdir@ datadir = @datadir@ datarootdir = @datarootdir@ devddir = @devddir@ docdir = @docdir@ driverexecdir = @driverexecdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ hotplugdir = @hotplugdir@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemdsystemshutdowndir = @systemdsystemshutdowndir@ systemdsystemunitdir = @systemdsystemunitdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udevdir = @udevdir@ BUILT_SOURCES = nutscan-usb.h nutscan-snmp.h @WITH_LIBLTDL_TRUE@lib_LTLIBRARIES = libnutscan.la libnutscan_la_SOURCES = scan_nut.c scan_ipmi.c \ nutscan-device.c nutscan-ip.c nutscan-display.c \ nutscan-init.c scan_usb.c scan_snmp.c scan_xml_http.c \ scan_avahi.c scan_eaton_serial.c nutscan-serial.c \ $(top_srcdir)/drivers/serial.c \ $(top_srcdir)/drivers/bcmxcp_ser.c \ $(top_srcdir)/common/common.c libnutscan_la_LIBADD = $(NETLIBS) $(LIBLTDL_LIBS) $(am__append_2) libnutscan_la_LDFLAGS = $(SERLIBS) -version-info 1:0:0 libnutscan_la_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include \ $(LIBLTDL_CFLAGS) -I$(top_srcdir)/drivers $(am__append_1) \ $(am__append_3) $(am__append_4) $(am__append_5) \ $(am__append_6) $(am__append_7) nut_scanner_SOURCES = nut-scanner.c nut_scanner_CFLAGS = -I$(top_srcdir)/clients -I$(top_srcdir)/include nut_scanner_LDADD = libnutscan.la ../../common/libcommon.la dist_noinst_HEADERS = nutscan-usb.h nutscan-snmp.h $(am__append_8) @WITH_DEV_TRUE@include_HEADERS = nut-scan.h nutscan-device.h nutscan-ip.h nutscan-init.h CLEANFILES = nutscan-usb.h nutscan-snmp.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/nut-scanner/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tools/nut-scanner/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libnutscan.la: $(libnutscan_la_OBJECTS) $(libnutscan_la_DEPENDENCIES) $(EXTRA_libnutscan_la_DEPENDENCIES) $(libnutscan_la_LINK) $(am_libnutscan_la_rpath) $(libnutscan_la_OBJECTS) $(libnutscan_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list nut-scanner$(EXEEXT): $(nut_scanner_OBJECTS) $(nut_scanner_DEPENDENCIES) $(EXTRA_nut_scanner_DEPENDENCIES) @rm -f nut-scanner$(EXEEXT) $(nut_scanner_LINK) $(nut_scanner_OBJECTS) $(nut_scanner_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-bcmxcp_ser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-nutscan-device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-nutscan-display.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-nutscan-init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-nutscan-ip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-nutscan-serial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_avahi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_eaton_serial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_ipmi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_nut.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_snmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-scan_xml_http.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnutscan_la-serial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nut_scanner-nut-scanner.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libnutscan_la-scan_nut.lo: scan_nut.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_nut.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_nut.Tpo -c -o libnutscan_la-scan_nut.lo `test -f 'scan_nut.c' || echo '$(srcdir)/'`scan_nut.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_nut.Tpo $(DEPDIR)/libnutscan_la-scan_nut.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_nut.c' object='libnutscan_la-scan_nut.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_nut.lo `test -f 'scan_nut.c' || echo '$(srcdir)/'`scan_nut.c libnutscan_la-scan_ipmi.lo: scan_ipmi.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_ipmi.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_ipmi.Tpo -c -o libnutscan_la-scan_ipmi.lo `test -f 'scan_ipmi.c' || echo '$(srcdir)/'`scan_ipmi.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_ipmi.Tpo $(DEPDIR)/libnutscan_la-scan_ipmi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_ipmi.c' object='libnutscan_la-scan_ipmi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_ipmi.lo `test -f 'scan_ipmi.c' || echo '$(srcdir)/'`scan_ipmi.c libnutscan_la-nutscan-device.lo: nutscan-device.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-nutscan-device.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-nutscan-device.Tpo -c -o libnutscan_la-nutscan-device.lo `test -f 'nutscan-device.c' || echo '$(srcdir)/'`nutscan-device.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-nutscan-device.Tpo $(DEPDIR)/libnutscan_la-nutscan-device.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nutscan-device.c' object='libnutscan_la-nutscan-device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-nutscan-device.lo `test -f 'nutscan-device.c' || echo '$(srcdir)/'`nutscan-device.c libnutscan_la-nutscan-ip.lo: nutscan-ip.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-nutscan-ip.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-nutscan-ip.Tpo -c -o libnutscan_la-nutscan-ip.lo `test -f 'nutscan-ip.c' || echo '$(srcdir)/'`nutscan-ip.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-nutscan-ip.Tpo $(DEPDIR)/libnutscan_la-nutscan-ip.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nutscan-ip.c' object='libnutscan_la-nutscan-ip.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-nutscan-ip.lo `test -f 'nutscan-ip.c' || echo '$(srcdir)/'`nutscan-ip.c libnutscan_la-nutscan-display.lo: nutscan-display.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-nutscan-display.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-nutscan-display.Tpo -c -o libnutscan_la-nutscan-display.lo `test -f 'nutscan-display.c' || echo '$(srcdir)/'`nutscan-display.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-nutscan-display.Tpo $(DEPDIR)/libnutscan_la-nutscan-display.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nutscan-display.c' object='libnutscan_la-nutscan-display.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-nutscan-display.lo `test -f 'nutscan-display.c' || echo '$(srcdir)/'`nutscan-display.c libnutscan_la-nutscan-init.lo: nutscan-init.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-nutscan-init.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-nutscan-init.Tpo -c -o libnutscan_la-nutscan-init.lo `test -f 'nutscan-init.c' || echo '$(srcdir)/'`nutscan-init.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-nutscan-init.Tpo $(DEPDIR)/libnutscan_la-nutscan-init.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nutscan-init.c' object='libnutscan_la-nutscan-init.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-nutscan-init.lo `test -f 'nutscan-init.c' || echo '$(srcdir)/'`nutscan-init.c libnutscan_la-scan_usb.lo: scan_usb.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_usb.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_usb.Tpo -c -o libnutscan_la-scan_usb.lo `test -f 'scan_usb.c' || echo '$(srcdir)/'`scan_usb.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_usb.Tpo $(DEPDIR)/libnutscan_la-scan_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_usb.c' object='libnutscan_la-scan_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_usb.lo `test -f 'scan_usb.c' || echo '$(srcdir)/'`scan_usb.c libnutscan_la-scan_snmp.lo: scan_snmp.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_snmp.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_snmp.Tpo -c -o libnutscan_la-scan_snmp.lo `test -f 'scan_snmp.c' || echo '$(srcdir)/'`scan_snmp.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_snmp.Tpo $(DEPDIR)/libnutscan_la-scan_snmp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_snmp.c' object='libnutscan_la-scan_snmp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_snmp.lo `test -f 'scan_snmp.c' || echo '$(srcdir)/'`scan_snmp.c libnutscan_la-scan_xml_http.lo: scan_xml_http.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_xml_http.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_xml_http.Tpo -c -o libnutscan_la-scan_xml_http.lo `test -f 'scan_xml_http.c' || echo '$(srcdir)/'`scan_xml_http.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_xml_http.Tpo $(DEPDIR)/libnutscan_la-scan_xml_http.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_xml_http.c' object='libnutscan_la-scan_xml_http.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_xml_http.lo `test -f 'scan_xml_http.c' || echo '$(srcdir)/'`scan_xml_http.c libnutscan_la-scan_avahi.lo: scan_avahi.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_avahi.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_avahi.Tpo -c -o libnutscan_la-scan_avahi.lo `test -f 'scan_avahi.c' || echo '$(srcdir)/'`scan_avahi.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_avahi.Tpo $(DEPDIR)/libnutscan_la-scan_avahi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_avahi.c' object='libnutscan_la-scan_avahi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_avahi.lo `test -f 'scan_avahi.c' || echo '$(srcdir)/'`scan_avahi.c libnutscan_la-scan_eaton_serial.lo: scan_eaton_serial.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-scan_eaton_serial.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-scan_eaton_serial.Tpo -c -o libnutscan_la-scan_eaton_serial.lo `test -f 'scan_eaton_serial.c' || echo '$(srcdir)/'`scan_eaton_serial.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-scan_eaton_serial.Tpo $(DEPDIR)/libnutscan_la-scan_eaton_serial.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scan_eaton_serial.c' object='libnutscan_la-scan_eaton_serial.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-scan_eaton_serial.lo `test -f 'scan_eaton_serial.c' || echo '$(srcdir)/'`scan_eaton_serial.c libnutscan_la-nutscan-serial.lo: nutscan-serial.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-nutscan-serial.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-nutscan-serial.Tpo -c -o libnutscan_la-nutscan-serial.lo `test -f 'nutscan-serial.c' || echo '$(srcdir)/'`nutscan-serial.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-nutscan-serial.Tpo $(DEPDIR)/libnutscan_la-nutscan-serial.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nutscan-serial.c' object='libnutscan_la-nutscan-serial.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-nutscan-serial.lo `test -f 'nutscan-serial.c' || echo '$(srcdir)/'`nutscan-serial.c libnutscan_la-serial.lo: $(top_srcdir)/drivers/serial.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-serial.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-serial.Tpo -c -o libnutscan_la-serial.lo `test -f '$(top_srcdir)/drivers/serial.c' || echo '$(srcdir)/'`$(top_srcdir)/drivers/serial.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-serial.Tpo $(DEPDIR)/libnutscan_la-serial.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/drivers/serial.c' object='libnutscan_la-serial.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-serial.lo `test -f '$(top_srcdir)/drivers/serial.c' || echo '$(srcdir)/'`$(top_srcdir)/drivers/serial.c libnutscan_la-bcmxcp_ser.lo: $(top_srcdir)/drivers/bcmxcp_ser.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-bcmxcp_ser.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-bcmxcp_ser.Tpo -c -o libnutscan_la-bcmxcp_ser.lo `test -f '$(top_srcdir)/drivers/bcmxcp_ser.c' || echo '$(srcdir)/'`$(top_srcdir)/drivers/bcmxcp_ser.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-bcmxcp_ser.Tpo $(DEPDIR)/libnutscan_la-bcmxcp_ser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/drivers/bcmxcp_ser.c' object='libnutscan_la-bcmxcp_ser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-bcmxcp_ser.lo `test -f '$(top_srcdir)/drivers/bcmxcp_ser.c' || echo '$(srcdir)/'`$(top_srcdir)/drivers/bcmxcp_ser.c libnutscan_la-common.lo: $(top_srcdir)/common/common.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -MT libnutscan_la-common.lo -MD -MP -MF $(DEPDIR)/libnutscan_la-common.Tpo -c -o libnutscan_la-common.lo `test -f '$(top_srcdir)/common/common.c' || echo '$(srcdir)/'`$(top_srcdir)/common/common.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libnutscan_la-common.Tpo $(DEPDIR)/libnutscan_la-common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/common/common.c' object='libnutscan_la-common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnutscan_la_CFLAGS) $(CFLAGS) -c -o libnutscan_la-common.lo `test -f '$(top_srcdir)/common/common.c' || echo '$(srcdir)/'`$(top_srcdir)/common/common.c nut_scanner-nut-scanner.o: nut-scanner.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nut_scanner_CFLAGS) $(CFLAGS) -MT nut_scanner-nut-scanner.o -MD -MP -MF $(DEPDIR)/nut_scanner-nut-scanner.Tpo -c -o nut_scanner-nut-scanner.o `test -f 'nut-scanner.c' || echo '$(srcdir)/'`nut-scanner.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nut_scanner-nut-scanner.Tpo $(DEPDIR)/nut_scanner-nut-scanner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nut-scanner.c' object='nut_scanner-nut-scanner.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nut_scanner_CFLAGS) $(CFLAGS) -c -o nut_scanner-nut-scanner.o `test -f 'nut-scanner.c' || echo '$(srcdir)/'`nut-scanner.c nut_scanner-nut-scanner.obj: nut-scanner.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nut_scanner_CFLAGS) $(CFLAGS) -MT nut_scanner-nut-scanner.obj -MD -MP -MF $(DEPDIR)/nut_scanner-nut-scanner.Tpo -c -o nut_scanner-nut-scanner.obj `if test -f 'nut-scanner.c'; then $(CYGPATH_W) 'nut-scanner.c'; else $(CYGPATH_W) '$(srcdir)/nut-scanner.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nut_scanner-nut-scanner.Tpo $(DEPDIR)/nut_scanner-nut-scanner.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nut-scanner.c' object='nut_scanner-nut-scanner.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nut_scanner_CFLAGS) $(CFLAGS) -c -o nut_scanner-nut-scanner.obj `if test -f 'nut-scanner.c'; then $(CYGPATH_W) 'nut-scanner.c'; else $(CYGPATH_W) '$(srcdir)/nut-scanner.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-includeHEADERS: $(include_HEADERS) @$(NORMAL_INSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ done uninstall-includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS \ uninstall-libLTLIBRARIES .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool ctags \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-includeHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-includeHEADERS uninstall-libLTLIBRARIES nutscan-usb.h nutscan-snmp.h: cd ..; $(MAKE) $(AM_MAKEFLAGS) nut-scanner-deps # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: nut-2.7.2/tools/nut-scanner/scan_avahi.c0000644000175000017500000003707312277355125015131 00000000000000/* scan_avahi.c: detect NUT avahi services * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut-scan.h" #ifdef WITH_AVAHI #include #include #include #include "timehead.h" #include #include #include #include #include #include /* dynamic link library stuff */ static char * libname = "libavahi-client"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; static AvahiClient* (*nut_avahi_service_browser_get_client)(AvahiServiceBrowser *); static int (*nut_avahi_simple_poll_loop)(AvahiSimplePoll *s); static void (*nut_avahi_client_free)(AvahiClient *client); static int (*nut_avahi_client_errno)(AvahiClient*); static void (*nut_avahi_free)(void *p); static void (*nut_avahi_simple_poll_quit)(AvahiSimplePoll *s); static AvahiClient* (*nut_avahi_client_new)( const AvahiPoll *poll_api, AvahiClientFlags flags, AvahiClientCallback callback, void *userdata, int *error); static void (*nut_avahi_simple_poll_free)(AvahiSimplePoll *s); static AvahiServiceResolver * (*nut_avahi_service_resolver_new)( AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain, AvahiProtocol aprotocol, AvahiLookupFlags flags, AvahiServiceResolverCallback callback, void *userdata); static const char * (*nut_avahi_strerror)(int error); static AvahiClient* (*nut_avahi_service_resolver_get_client)(AvahiServiceResolver *); static AvahiServiceBrowser* (*nut_avahi_service_browser_new)( AvahiClient *client, AvahiIfIndex interface, AvahiProtocol protocol, const char *type, const char *domain, AvahiLookupFlags flags, AvahiServiceBrowserCallback callback, void *userdata); static int (*nut_avahi_service_resolver_free)(AvahiServiceResolver *r); static AvahiSimplePoll *(*nut_avahi_simple_poll_new)(void); static char* (*nut_avahi_string_list_to_string)(AvahiStringList *l); static int (*nut_avahi_service_browser_free)(AvahiServiceBrowser *); static char * (*nut_avahi_address_snprint)(char *ret_s, size_t length, const AvahiAddress *a); static const AvahiPoll* (*nut_avahi_simple_poll_get)(AvahiSimplePoll *s); /* return 0 on error */ int nutscan_load_avahi_library() { if( dl_handle != NULL ) { /* if previous init failed */ if( dl_handle == (void *)1 ) { return 0; } /* init has already been done */ return 1; } if( lt_dlinit() != 0 ) { fprintf(stderr, "Error initializing lt_init\n"); return 0; } dl_handle = lt_dlopenext(libname); if (!dl_handle) { dl_error = lt_dlerror(); goto err; } lt_dlerror(); /* Clear any existing error */ *(void **) (&nut_avahi_service_browser_get_client) = lt_dlsym(dl_handle, "avahi_service_browser_get_client"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_simple_poll_loop) = lt_dlsym(dl_handle, "avahi_simple_poll_loop"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_client_free) = lt_dlsym(dl_handle, "avahi_client_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_client_errno) = lt_dlsym(dl_handle, "avahi_client_errno"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_free) = lt_dlsym(dl_handle, "avahi_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_simple_poll_quit) = lt_dlsym(dl_handle, "avahi_simple_poll_quit"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_client_new) = lt_dlsym(dl_handle, "avahi_client_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_simple_poll_free) = lt_dlsym(dl_handle, "avahi_simple_poll_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_service_resolver_new) = lt_dlsym(dl_handle, "avahi_service_resolver_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_strerror) = lt_dlsym(dl_handle, "avahi_strerror"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_service_resolver_get_client) = lt_dlsym(dl_handle, "avahi_service_resolver_get_client"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_service_browser_new) = lt_dlsym(dl_handle, "avahi_service_browser_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_service_resolver_free) = lt_dlsym(dl_handle, "avahi_service_resolver_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_simple_poll_new) = lt_dlsym(dl_handle, "avahi_simple_poll_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_string_list_to_string) = lt_dlsym(dl_handle, "avahi_string_list_to_string"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_service_browser_free) = lt_dlsym(dl_handle, "avahi_service_browser_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_address_snprint) = lt_dlsym(dl_handle, "avahi_address_snprint"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_avahi_simple_poll_get) = lt_dlsym(dl_handle, "avahi_simple_poll_get"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } return 1; err: fprintf(stderr, "Cannot load AVAHI library (%s) : %s. AVAHI search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; } /* end of dynamic link library stuff */ static AvahiSimplePoll *simple_poll = NULL; static nutscan_device_t * dev_ret = NULL; static long avahi_usec_timeout = 0; static void update_device(const char * host_name,const char *ip, uint16_t port,char * text, int proto) { nutscan_device_t * dev = NULL; char * t = NULL; char * t_saveptr = NULL; char * phrase = NULL; char * phrase_saveptr = NULL; char * word = NULL; char * value = NULL; char * device = NULL; char * device_saveptr = NULL; int device_found = 0; char buf[6]; int buf_size; if( text == NULL ) { return; } t = strdup(text); phrase = strtok_r(t,"\"",&t_saveptr); while(phrase != NULL ) { word = strtok_r(phrase,"=",&phrase_saveptr); if( word == NULL ) { phrase = strtok_r(NULL,"\"",&t_saveptr); continue; } value = strtok_r(NULL,"=",&phrase_saveptr); if( value == NULL ) { phrase = strtok_r(NULL,"\"",&t_saveptr); continue; } if( strcmp(word,"device_list") != 0 ) { phrase = strtok_r(NULL,"\"",&t_saveptr); continue; } device = strtok_r(value,";",&device_saveptr); while( device != NULL ) { device_found = 1; dev = nutscan_new_device(); dev->type = TYPE_NUT; dev->driver = strdup("nutclient"); if( proto == AVAHI_PROTO_INET) { nutscan_add_option_to_device(dev,"desc","IPv4"); } if( proto == AVAHI_PROTO_INET6 ) { nutscan_add_option_to_device(dev,"desc","IPv6"); } if( port != PORT) { /* +5+1+1+1 is for : - port number (max 65535 so 5 characters), - '@' and ':' characters - terminating 0 */ buf_size = strlen(device)+strlen(host_name)+ 5+1+1+1; dev->port=malloc(buf_size); if(dev->port) { snprintf(dev->port,buf_size,"%s@%s:%u", device,host_name,port); } } else { /*+1+1 is for '@' character and terminating 0 */ buf_size = strlen(device)+strlen(host_name)+1+1; dev->port=malloc(buf_size); if(dev->port) { snprintf(dev->port,buf_size,"%s@%s", device,host_name); } } if( dev->port ) { dev_ret = nutscan_add_device_to_device(dev_ret,dev); } else { nutscan_free_device(dev); } device = strtok_r(NULL,";",&device_saveptr); }; phrase = strtok_r(NULL,"\"",&t_saveptr); }; free(t); /* If no device published in avahi data, try to get the device by connecting directly to upsd */ if( !device_found) { snprintf(buf,sizeof(buf),"%u",port); dev = nutscan_scan_nut(ip,ip,buf,avahi_usec_timeout); if(dev) { dev_ret = nutscan_add_device_to_device(dev_ret,dev); } /* add an upsd entry without associated device */ else { dev = nutscan_new_device(); dev->type = TYPE_NUT; dev->driver = strdup("nutclient"); if( proto == AVAHI_PROTO_INET) { nutscan_add_option_to_device(dev,"desc","IPv4"); } if( proto == AVAHI_PROTO_INET6 ) { nutscan_add_option_to_device(dev,"desc","IPv6"); } if( port != PORT) { /*+1+1 is for ':' character and terminating 0 */ /*buf is the string containing the port number*/ buf_size = strlen(host_name)+strlen(buf)+1+1; dev->port=malloc(buf_size); if(dev->port) { snprintf(dev->port,buf_size,"%s:%s", host_name,buf); } } else { dev->port=strdup(host_name); } if( dev->port ) { dev_ret = nutscan_add_device_to_device(dev_ret,dev); } else { nutscan_free_device(dev); } } } } static void resolve_callback( AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, AVAHI_GCC_UNUSED void* userdata) { assert(r); /* Called whenever a service has been resolved successfully or timed out */ switch (event) { case AVAHI_RESOLVER_FAILURE: fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, (*nut_avahi_strerror)((*nut_avahi_client_errno)((*nut_avahi_service_resolver_get_client)(r)))); break; case AVAHI_RESOLVER_FOUND: { char a[AVAHI_ADDRESS_STR_MAX], *t; /* fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain); */ (*nut_avahi_address_snprint)(a, sizeof(a), address); t = (*nut_avahi_string_list_to_string)(txt); /* fprintf(stderr, "\t%s:%u (%s)\n" "\tTXT=%s\n" "\tcookie is %u\n" "\tis_local: %i\n" "\tour_own: %i\n" "\twide_area: %i\n" "\tmulticast: %i\n" "\tcached: %i\n", host_name, port, a, t, avahi_string_list_get_service_cookie(txt), !!(flags & AVAHI_LOOKUP_RESULT_LOCAL), !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN), !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA), !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST), !!(flags & AVAHI_LOOKUP_RESULT_CACHED)); */ update_device(host_name,a,port,t,address->proto); (*nut_avahi_free)(t); } } (*nut_avahi_service_resolver_free)(r); } static void browse_callback( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata) { AvahiClient *c = userdata; assert(b); /* Called whenever a new services becomes available on the LAN or is removed from the LAN */ switch (event) { case AVAHI_BROWSER_FAILURE: fprintf(stderr, "(Browser) %s\n", (*nut_avahi_strerror)((*nut_avahi_client_errno)((*nut_avahi_service_browser_get_client)(b)))); (*nut_avahi_simple_poll_quit)(simple_poll); return; case AVAHI_BROWSER_NEW: /* fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); */ /* We ignore the returned resolver object. In the callback function we free it. If the server is terminated before the callback function is called the server will free the resolver for us. */ if (!((*nut_avahi_service_resolver_new)(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c))) fprintf(stderr, "Failed to resolve service '%s': %s\n", name, (*nut_avahi_strerror)((*nut_avahi_client_errno)(c))); break; case AVAHI_BROWSER_REMOVE: fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain); break; case AVAHI_BROWSER_ALL_FOR_NOW: (*nut_avahi_simple_poll_quit)(simple_poll); case AVAHI_BROWSER_CACHE_EXHAUSTED: /* fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); */ break; } } static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) { assert(c); /* Called whenever the client or server state changes */ if (state == AVAHI_CLIENT_FAILURE) { fprintf(stderr, "Server connection failure: %s\n", (*nut_avahi_strerror)((*nut_avahi_client_errno)(c))); (*nut_avahi_simple_poll_quit)(simple_poll); } } nutscan_device_t * nutscan_scan_avahi(long usec_timeout) { /* Example service publication * $ avahi-publish -s nut _upsd._tcp 3493 txtvers=1 protovers=1.0.0 device_list="dev1;dev2" */ AvahiClient *client = NULL; AvahiServiceBrowser *sb = NULL; int error; if( !nutscan_avail_avahi ) { return NULL; } avahi_usec_timeout = usec_timeout; /* Allocate main loop object */ if (!(simple_poll = (*nut_avahi_simple_poll_new)())) { fprintf(stderr, "Failed to create simple poll object.\n"); goto fail; } /* Allocate a new client */ client = (*nut_avahi_client_new)((*nut_avahi_simple_poll_get)(simple_poll), 0, client_callback, NULL, &error); /* Check wether creating the client object succeeded */ if (!client) { fprintf(stderr, "Failed to create client: %s\n", (*nut_avahi_strerror)(error)); goto fail; } /* Create the service browser */ if (!(sb = (*nut_avahi_service_browser_new)(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_upsd._tcp", NULL, 0, browse_callback, client))) { fprintf(stderr, "Failed to create service browser: %s\n", (*nut_avahi_strerror)((*nut_avahi_client_errno)(client))); goto fail; } /* Run the main loop */ (*nut_avahi_simple_poll_loop)(simple_poll); fail: /* Cleanup things */ if (sb) (*nut_avahi_service_browser_free)(sb); if (client) (*nut_avahi_client_free)(client); if (simple_poll) (*nut_avahi_simple_poll_free)(simple_poll); return nutscan_rewind_device(dev_ret); } #else /* WITH_AVAHI */ /* stub function */ nutscan_device_t * nutscan_scan_avahi(long usec_timeout) { return NULL; } #endif /* WITH_AVAHI */ nut-2.7.2/tools/nut-scanner/nutscan-display.c0000644000175000017500000000507612277355125016151 00000000000000/* display.c: format and display scanned devices * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include #include "nutscan-device.h" char * nutscan_device_type_string[TYPE_END]= { "NONE", "USB", "SNMP", "XML", "NUT", "IPMI", "AVAHI", "EATON_SERIAL" }; void nutscan_display_ups_conf(nutscan_device_t * device) { nutscan_device_t * current_dev = device; nutscan_options_t * opt; static int nutdev_num = 1; if(device==NULL) { return; } /* Find start of the list */ while(current_dev->prev != NULL) { current_dev = current_dev->prev; } /* Display each devices */ do { printf("[nutdev%i]\n\tdriver = \"%s\"\n\tport = \"%s\"\n", nutdev_num, current_dev->driver, current_dev->port); opt = current_dev->opt; while (NULL != opt) { if( opt->option != NULL ) { printf("\t%s",opt->option); if( opt->value != NULL ) { printf(" = \"%s\"", opt->value); } printf("\n"); } opt = opt->next; } nutdev_num++; current_dev = current_dev->next; } while( current_dev != NULL ); } void nutscan_display_parsable(nutscan_device_t * device) { nutscan_device_t * current_dev = device; nutscan_options_t * opt; if(device==NULL) { return; } /* Find start of the list */ while(current_dev->prev != NULL) { current_dev = current_dev->prev; } /* Display each devices */ do { printf("%s:driver=\"%s\",port=\"%s\"", nutscan_device_type_string[current_dev->type], current_dev->driver, current_dev->port); opt = current_dev->opt; while (NULL != opt) { if( opt->option != NULL ) { printf(",%s",opt->option); if( opt->value != NULL ) { printf("=\"%s\"", opt->value); } } opt = opt->next; } printf("\n"); current_dev = current_dev->next; } while( current_dev != NULL ); } nut-2.7.2/tools/nut-scanner/nutscan-device.h0000644000175000017500000000446012277355125015744 00000000000000/* device.h: definition of a container describing a NUT device * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SCAN_DEVICE #define SCAN_DEVICE #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /** * \brief Device type string getter * * \param type Device type * * \return Type string */ #define nutscan_device_type_string(type) \ (assert(0 < (type) && (type) < TYPE_END), nutscan_device_type_strings[type - 1]) typedef enum nutscan_device_type { TYPE_NONE=0, TYPE_USB, TYPE_SNMP, TYPE_XML, TYPE_NUT, TYPE_IPMI, TYPE_AVAHI, TYPE_EATON_SERIAL, TYPE_END } nutscan_device_type_t; /** Device type -> string mapping */ extern const char * nutscan_device_type_strings[TYPE_END - 1]; typedef struct nutscan_options { char * option; char * value; struct nutscan_options* next; } nutscan_options_t; typedef struct nutscan_device { nutscan_device_type_t type; char * driver; char * port; nutscan_options_t * opt; struct nutscan_device * prev; struct nutscan_device * next; } nutscan_device_t; nutscan_device_t * nutscan_new_device(); void nutscan_free_device(nutscan_device_t * device); void nutscan_add_option_to_device(nutscan_device_t * device,char * option, char * value); nutscan_device_t * nutscan_add_device_to_device(nutscan_device_t * first, nutscan_device_t * second); /** * \brief Rewind device list * * \param device Device list item * * \return Device list head */ nutscan_device_t * nutscan_rewind_device(nutscan_device_t * device); #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #endif nut-2.7.2/tools/nut-scanner/nut-scan.h0000644000175000017500000000642512277355125014567 00000000000000/* nut-scan.h: detect NUT services * * Copyright (C) * 2011 - Frederic Bohe * 2012 - Arnaud Quette * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef NUT_SCAN_H #define NUT_SCAN_H #include #include #include #ifdef WITH_IPMI #include #endif #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* SNMP structure */ typedef struct nutscan_snmp { char * community; char * secLevel; char * secName; char * authPassword; char * privPassword; char * authProtocol; char * privProtocol; char * peername; void * handle; } nutscan_snmp_t; /* IPMI structure */ /* Settings for OutofBand (remote) connection */ typedef struct nutscan_ipmi { char* username; /* IPMI 1.5 and 2.0 */ char* password; /* IPMI 1.5 and 2.0 */ int authentication_type; /* IPMI 1.5 */ int cipher_suite_id; /* IPMI 2.0 */ char* K_g_BMC_key; /* IPMI 2.0, optional key for 2 key auth. */ int privilege_level; /* for both */ unsigned int workaround_flags; /* for both */ int ipmi_version; /* IPMI 1.5 or 2.0? */ } nutscan_ipmi_t; /* IPMI auth defines, simply using FreeIPMI defines */ #ifndef IPMI_AUTHENTICATION_TYPE_NONE #define IPMI_AUTHENTICATION_TYPE_NONE 0x00 #define IPMI_AUTHENTICATION_TYPE_MD2 0x01 #define IPMI_AUTHENTICATION_TYPE_MD5 0x02 #define IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY 0x04 #define IPMI_AUTHENTICATION_TYPE_OEM_PROP 0x05 #define IPMI_AUTHENTICATION_TYPE_RMCPPLUS 0x06 #endif #ifndef IPMI_PRIVILEGE_LEVEL_ADMIN #define IPMI_PRIVILEGE_LEVEL_ADMIN 0x04 #endif #define IPMI_1_5 1 #define IPMI_2_0 0 /* Scanning */ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip, long usec_timeout, nutscan_snmp_t * sec); nutscan_device_t * nutscan_scan_usb(); nutscan_device_t * nutscan_scan_xml_http(long usec_timeout); nutscan_device_t * nutscan_scan_nut(const char * startIP, const char * stopIP, const char * port, long usec_timeout); nutscan_device_t * nutscan_scan_avahi(long usec_timeout); nutscan_device_t * nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec); nutscan_device_t * nutscan_scan_eaton_serial(const char* ports_list); /* Display functions */ void nutscan_display_ups_conf(nutscan_device_t * device); void nutscan_display_parsable(nutscan_device_t * device); #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #endif nut-2.7.2/tools/nut-scanner/nutscan-init.h0000644000175000017500000000236012277355125015445 00000000000000/* nutscan-init.h: initialisation data * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SCAN_INIT #define SCAN_INIT #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif extern int nutscan_avail_avahi; extern int nutscan_avail_ipmi; extern int nutscan_avail_nut; extern int nutscan_avail_snmp; extern int nutscan_avail_usb; extern int nutscan_avail_xml_http; void nutscan_init(void); void nutscan_free(void); #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #endif nut-2.7.2/tools/nut-scanner/scan_xml_http.c0000644000175000017500000001530312301203177015653 00000000000000/* scan_xml_http.c: detect NUT supported XML HTTP devices * * Copyright (C) 2011 - Frederic Bohe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut-scan.h" #ifdef WITH_NEON #include #include #include #include #include #include #include #include #include #include #include /* dynamic link library stuff */ static char * libname = "libneon"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; static void (*nut_ne_xml_push_handler)(ne_xml_parser *p, ne_xml_startelm_cb *startelm, ne_xml_cdata_cb *cdata, ne_xml_endelm_cb *endelm, void *userdata); static void (*nut_ne_xml_destroy)(ne_xml_parser *p); static ne_xml_parser * (*nut_ne_xml_create)(void); static int (*nut_ne_xml_parse)(ne_xml_parser *p, const char *block, size_t len); /* return 0 on error */ int nutscan_load_neon_library() { if( dl_handle != NULL ) { /* if previous init failed */ if( dl_handle == (void *)1 ) { return 0; } /* init has already been done */ return 1; } if( lt_dlinit() != 0 ) { fprintf(stderr, "Error initializing lt_init\n"); return 0; } dl_handle = lt_dlopenext(libname); if (!dl_handle) { dl_error = lt_dlerror(); goto err; } lt_dlerror(); /* Clear any existing error */ *(void **) (&nut_ne_xml_push_handler) = lt_dlsym(dl_handle, "ne_xml_push_handler"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ne_xml_destroy) = lt_dlsym(dl_handle,"ne_xml_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ne_xml_create) = lt_dlsym(dl_handle,"ne_xml_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_ne_xml_parse) = lt_dlsym(dl_handle,"ne_xml_parse"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } return 1; err: fprintf(stderr, "Cannot load XML library (%s) : %s. XML search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; } static int startelm_cb(void *userdata, int parent, const char *nspace, const char *name, const char **atts) { nutscan_device_t * dev = (nutscan_device_t *)userdata; char buf[SMALLBUF]; int i = 0; while( atts[i] != NULL ) { if(strcmp(atts[i],"type") == 0) { snprintf(buf,sizeof(buf),"%s",atts[i+1]); nutscan_add_option_to_device(dev,"desc",buf); return 0; } i=i+2; } return 0; } nutscan_device_t * nutscan_scan_xml_http(long usec_timeout) { char *scanMsg = ""; int port = 4679; int peerSocket; int sockopt_on = 1; struct sockaddr_in sockAddress; socklen_t sockAddressLength = sizeof(sockAddress); memset(&sockAddress, 0, sizeof(sockAddress)); fd_set fds; struct timeval timeout; int ret; char buf[SMALLBUF]; char string[SMALLBUF]; ssize_t recv_size; nutscan_device_t * nut_dev = NULL; nutscan_device_t * current_nut_dev = NULL; if( !nutscan_avail_xml_http ) { return NULL; } if((peerSocket = socket(AF_INET, SOCK_DGRAM, 0)) != -1) { /* Initialize socket */ sockAddress.sin_family = AF_INET; sockAddress.sin_addr.s_addr = INADDR_BROADCAST; sockAddress.sin_port = htons(port); setsockopt(peerSocket, SOL_SOCKET, SO_BROADCAST, &sockopt_on, sizeof(sockopt_on)); /* Send scan request */ if(sendto(peerSocket, scanMsg, strlen(scanMsg), 0, (struct sockaddr *)&sockAddress, sockAddressLength) <= 0) { fprintf(stderr,"Error sending Eaton \n"); } else { FD_ZERO(&fds); FD_SET(peerSocket,&fds); timeout.tv_sec = usec_timeout / 1000000; timeout.tv_usec = usec_timeout % 1000000; while ((ret=select(peerSocket+1,&fds,NULL,NULL, &timeout) )) { timeout.tv_sec = usec_timeout / 1000000; timeout.tv_usec = usec_timeout % 1000000; if( ret == -1 ) { fprintf(stderr, "Error waiting on \ socket: %d\n",errno); break; } sockAddressLength = sizeof(struct sockaddr_in); recv_size = recvfrom(peerSocket,buf, sizeof(buf),0, (struct sockaddr *)&sockAddress, &sockAddressLength); if(recv_size==-1) { fprintf(stderr, "Error reading \ socket: %d\n",errno); continue; } if( getnameinfo( (struct sockaddr *)&sockAddress, sizeof(struct sockaddr_in),string, sizeof(string),NULL,0, NI_NUMERICHOST) != 0) { fprintf(stderr, "Error converting IP address \ : %d\n",errno); continue; } nut_dev = nutscan_new_device(); if(nut_dev == NULL) { fprintf(stderr,"Memory allocation \ error\n"); return NULL; } nut_dev->type = TYPE_XML; /* Try to read device type */ ne_xml_parser *parser = (*nut_ne_xml_create)(); (*nut_ne_xml_push_handler)(parser, startelm_cb, NULL, NULL, nut_dev); (*nut_ne_xml_parse)(parser, buf, recv_size); (*nut_ne_xml_destroy)(parser); nut_dev->driver = strdup("netxml-ups"); sprintf(buf,"http://%s",string); nut_dev->port = strdup(buf); current_nut_dev = nutscan_add_device_to_device( current_nut_dev,nut_dev); } } } else { fprintf(stderr,"Error creating socket\n"); } return nutscan_rewind_device(current_nut_dev); } #else /* WITH_NEON */ nutscan_device_t * nutscan_scan_xml_http(long usec_timeout) { return NULL; } #endif /* WITH_NEON */ nut-2.7.2/NEWS0000644000175000017500000017431512324031655007764 00000000000000If you're upgrading from an earlier version, see the UPGRADING file. For a complete and more detailed list of changes, please refer to the ChangeLog file. --------------------------------------------------------------------------- Release notes for NUT 2.7.2 - what's new since 2.7.1: - This release is the second interim release of the 2.7 testing series. - libupsclient had undefined references related to functions of libcommon. This issue was reported on Debian (bug #731156) and is now fixed - support for new devices: CABAC UPS-1700DV2 Eaton Powerware 3105 Emerson Network Power Liebert PSI 1440 MicroDowell B.Box LP 500 Numeric Digital 800 plus OptiUPS VS 575C Tripp Lite SU10KRT3/1X - FreeDesktop Hardware Abstraction Layer (HAL) support was removed. - nutdrv_atcl_usb: new driver for 'ATCL FOR UPS' - al175: re-introduced this driver (actually, it was in 2.7.1) - upsdrvctl now provides retry options for upsdrvctl and driver(s) - snmp-ups: add support for XPPC-MIB and Tripp Lite SU10KRT3/1X. Also fix erroneous status in HP/Compaq SNMP MIB (with the most recent HP firmware (1.76) ; improved various MIBs (APC, HP/Compaq, ...) - nutdrv_qx: add new 'fallback' Q1 subdriver, with minimal 'Q1' support. General improvements on all subdrivers. - mge-shut: partially revert PnP/RTS change, for initializing the communication with the UPS. Note that nut-scanner similar function was not modified however. - FreeBSD DEVD support: generate devd.conf files for USB UPSes This adds a --with-devd-dir=PATH option to ./configure - The NUT website was moved to a standalone website. A separate code repository and source archive are now available. - As usual, more bugfixes, cleanup and improvements, on both source code and documentation. --------------------------------------------------------------------------- Release notes for NUT 2.7.1 - what's new since 2.6.5: - This release is an interim release, part of the testing series, and the first release after the transition from Subversion to Git. The last release (2.6.5) is almost a year old. A lot of work has been done, but a good amount remains to achieve 2.8.0 goals. Please read the UPGRADING notes. - Added support for SSL via the Mozilla NSS library, in addition to the existing OpenSSL support. - Added a new driver, nutdrv_qx, for Megatec/Qx devices. This driver will eventually replace the blazer_ser and blazer_usb drivers. In particular, it adds support for Voltronic Power devices. - Increased USB_TIMEOUT to standards-compliant 5.000 seconds in most drivers. This should reduce the number of timeouts on low-speed USB 1.1 devices. - The jNut Java source has been split into a separate GitHub repository. - Added many devices to the HCL. Of particular note are many Tripp Lite USB HID PDC models which were tested against NUT by Tripp Lite. - Reworked some visual elements of the HCL. The output is better tailored for graphical and text-only browsers, but suggestions are welcome for additional accessibility enhancements. - Also increased timeouts and added redundant commands to improve reliability of mge-utalk driver. - Added the apcupsd-ups driver to interoperate with apcupsd installations. - Added documentation on creating subdrivers for snmp-ups and nutdrv_qx. - Added new drivers for the Riello UPS product line (riello_ser/riello_usb). - Many improvements to the BCM/XCP drivers have been merged in. This includes an improved data reception loop, and additional mappings. - Added a few variables to the Powercom HID mappings. - Updated the apcsmart driver, and renamed the previous driver to apcsmart-old. - Fixed the battery percentage calculation in the bestfcom driver. - libnutclient has been added as a C++ alternative to libupsclient. - Packaging files for Solaris and HP-UX (sponsored by Eaton) - Fix shutdown of Eaton HID, using usbhid-ups and mge-shut - usbhid-ups: final fix for APC Back UPS ES. APC Back UPS ES devices have buggy firmware, and this version does not cause a regression. The max_report variable should be set automatically based on the USB identification values. - nut-scanner: fix crash - IPMI support can handle more different versions of FreeIPMI - Support power supplies scan over the network nut-scanner can now scan for power supplies with IPMI over LAN. This is currently limited to IPMI 1.5 only - Implement a framework to spell check documentation source files, using Aspell. This includes an interactive build target (make spellcheck-interactive), and an automated one (make spellcheck), mainly for QA / Buildbot purpose. Note that a base NUT dictionary is also available (docs/nut.dict), providing a glossary of terms related to power devices and management - Improve systemd integration - snmp-ups: Fixed a crash on outlet management, and added delta_ups MIB support. Also fixed mappings for upsBypassVoltage, upsBypassCurrent, and upsBypassPower in three-phase IETF MIB. --------------------------------------------------------------------------- Release notes for NUT 2.6.5 - what's new since 2.6.4: - This release fixes an important regression in upssched: any upssched.conf command that takes a second argument resulted in a defective frame sent to the parent process. Thus, the command was not executed (report and patch from Oliver Schonefeld) - Website hosting: free NUT from Eaton website hosting NUT website (http://www.networkupstools.org) is no longer hosted by Eaton. Arnaud Quette (NUT project leader) has taken over NUT hosting on his own, to give NUT back some independence. This effort is also part of a logic to stop crediting Eaton for contributions from others (especially Arnaud Quette, as an individual). The new hosting service is located, as for Arnaud's blog (http://arnaud.quette.fr) on Gandi servers, using PaaS. This will allow more flexibility and automation of the release process - macosx-ups: new OS X Power Sources meta-driver Mac OS X provides UPS status information in a format similar to what is shown for laptop batteries. This driver will convert that information into a format compatible with NUT (Charles Lepple). - support for new devices: Eaton ePDU Switched Online Zinto A (USB ID 0x06da:0x0601) REDi Blazer 400VA / 600VA / 800VA UNITEK Alpha650ipF and Alpha650ipE (USB ID 0x0f03:0x0001) - mge-shut driver has been replaced by a new implementation (newmge-shut). In case of issue with this new version, users can revert to oldmge-shut. - First NUT virtualization package: NUT now supports integration with VMware ESXI 5.0, through a native VIB package. This is, for the time being, an external effort from René Garcia (refer to the Download section on NUT website). But work is underway to improve this integration, and include it in the NUT source tree - IPMI support (nut-ipmipsu driver and nut-scanner): prepare for supporting API changes in upcoming FreeIPMI versions 1.1.x and 1.2.x. - snmp-ups now supports high precision values for APC, and more variables - the NUT variables and commands namespace has been fixed and completed, with the known and used variables that were missing. - more bugfixes, cleanup and improvements, on both source code and documentation. --------------------------------------------------------------------------- Release notes for NUT 2.6.4 - what's new since 2.6.3: - This release Fix an important vulnerability in upsd (CVE-2012-2944: upsd can be remotely crashed) NUT server (upsd), from versions 2.4.0 to 2.6.3, are exposed to crashes when receiving random data from the network. This issue is related to the way NUT parses characters, especially from the network. Non printable characters were missed from strings operation (such as strlen), but still copied to the buffer, causing an overflow. Thus, fix NUT parser, to only allow the subset Ascii charset from Space to ~ (Reported by Sebastian Pohle, Alioth bug #313636, CVE-2012-2944) A separate patch, which applies to any faulty version, is also available: http://trac.networkupstools.org/projects/nut/changeset/3633 For more information, refer to the Common Vulnerabilities and Exposures: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-2944 - A static source code analysis has been done by Michal Hlavinka from RedHat, using Coverity (12 issues fixed). - Add new "LIST CLIENTS" and "NETVER" commands to NUT network protocol. "NETVER" allows to retrieve the Network protocol version, while "LIST CLIENTS" provides the list of clients connected to a device. Refer to the developer guide, "Network protocol information" section for more information. - Support of ranges of values for writable variables has been added, to complete the existing enumerated values mechanism. This will start to appear in some drivers soon, beginning with Eaton. Refer to the developer guide, "Creating a new driver..." section for more information. - PyNUT.py has been updated to version 1.2.2, adding support for LIST CLIENTS, FSD, HELP and VER (Rene Martín Rodríguez) - support for new devices: AEG Power Solutions PROTECT HOME more APC SNMP cards ATEK Defensor range all Borri models all COVER ENERGY SA CyberPower OR700LCDRM1U, PR6000LCDRTXL5U and CP1000PFCLCD Dell UPS Network Management Card Dynamix 1000VA USB Eaton Management Card Contact (ref 66104) EVER POWERLINE RT / 11 / 31 and DUO II Pro GE Digital Energy GT Series 1000-3000 VA Gtec models all recent HP serial / USB UPS (G2, G3 and R/T models, ) and HP UPS Management Module Ippon INNOVA RT KOLFF BLACK NOVA Lexis X-power Tigra 1kVA Microline C-Lion Innova Online Yunto YQ450 PowerShield Defender 1200VA PowerWalker Online VFI LCD, Line-Interactive VI LCD and Line-Interactive VI Riello Netman Plus 102 SNMP Card Tripp-Lite OMNISMART500 - apcsmart has received some fixes to work better on Mac OS X, and in general - bcmxcp has improved support for battery status, and better supports PW9120 units - bestfortress has improved Best Fortress LI675VA support - blazer_ser and blazer_usb now try to automatically estimate high and low voltages, to be able to calculate battery charge ; support for online Innova UPS (T, RT and 3/1 T) has been added ; Best UPS support has been improved, to prepare for superseeding bestups driver - bestups has also received some care, though users are encouraged to switch to blazer_ser, since bestups will soon be deprecated. - newmge-shut has been heavilly improved. However, replacement of the current mge-shut has been postponed to the next release, due to the CVE issue. - oneac 0.80 improves support for all families of Oneac (EG, ON, OZ and OB), including more data and instant commands (Bill Elliot). - usbhid-ups: for Eaton devices, ups.start.auto is now automatically adjusted for shutdown.{return,stayoff} to behave as expected ; Liebert firmwares with incorrect exponents have also been addressed. - snmp-ups now provides support for UPS shutdown, based on usbhid-ups mechanisms (composite commands and fallback). Composite commands are also supported now. This means, for example, that if 'shutdown.return' is not supported, a combination of 'load.off' + 'load.on' may be used ; Actual validity of instant commands is now tested before commands addition ; Eaton/MGE MIB has been cleaned and completed ; 3-phases support has been added to Socomec Netvision MIB ; HP/Compaq MIB has been completed, with thresholds, nominal values and more commands. - nut-scanner now also has libupsclient has a weak runtime dependency ; more docs and bugfixes have also happened. - Provide an Uncomplicated Firewall (UFW) profile (nut.ufw.profile) - Riello protocols have been officially published in NUT protocols library: http://www.networkupstools.org/ups-protocols.html#_riello - Duplicate instances of upsd / upsmon are now detected upon startup - NUT variables namespace has been completed with missing variables and commands that are already known and standard - upslog now comes with a companion file, for logrotate configuration - more devices embed NUT for power protection, now including Thecus NAS range - more bugfixes, cleanup and improvements, on both source code and documentation, with a good bunch from Greg A. Woods. --------------------------------------------------------------------------- Release notes for NUT 2.6.3 - what's new since 2.6.2: - nut-scanner is now more portable, and provides more coherent option names. IPMI support has also been added, to discover local power supplies. This version brings weak runtime dependencies in libnutscan, which allows to compile nut-scanner with all options and to run according to the available dependencies (USB, SNMP, IPMI, ...). - libnutscan now provides pkg-config support and the needed header files are distributed. Some documentation is also available in the developer guide and manual pages have been updated and completed. - support for new devices: Cyber Power Systems with SNMP RMCARD (100, 201, 202 and 301) ; Dynamix 650VA USB ; LDLC UPS-1200D ; Tecnoware UPS ERA LCD 0.65 ; Powercom BNT-xxxAP (USB ID 0d9f:0004) ; Various USB devices using UPSilon 2000 software. - apcsmart has received minor correction. - bcmxcp_usb now handles disconnection issues and reconnection mechanism. - blazer_usb enables again inclusion of buggy USB Device and Vendor IDs in udev rules file ; language ID support has been added for USB units from LDLC, Dynamix and other no names. - nut-ipmipsu has also received some improvements. - snmp-ups has fixed outlets reported current in aphel_genesisII MIB ; MGE 3 phases handles better low battery condition ; support for Cyber Power Systems with SNMP RMCARD has been added ; support of the newer Eaton ePDUs has been improved. - upsd doesn't anymore fail to start if at least one of the listening interface is available. This is needed on systems where either IPv4 or IPv6 is disabled, and no explicit LISTEN directive has been specified. - Avahi support is now automatically enabled, upon detection - jNut (NUT Java interface) adds device discovery support, through a nut-scanner wrapper ; jNutWebAPI, a HTTP/JSON web service interface, has also been added to interact with upsd and nut-scanner. - Base files for HPUX packaging have been added. This is still a work in progress. - Compilation on IBM Aix has been fixed (namespace conflict with ctypes). - more bugfixes, cleanup and improvements, on both source code and documentation. --------------------------------------------------------------------------- Release notes for NUT 2.6.2 - what's new since 2.6.1: - NUT can now monitor power supply units (PSU) in servers, through IPMI, using the new experimental 'nut-ipmipsu' driver. Users are encouraged to test it, and send feedback and debug output to the development mailing list. This requires GNU FreeIPMI (0.8.5 or higher) development package or files. Thanks goes to Al Chu, FreeIPMI project leader, for his help during this development. - NUT now provides a tool, called 'nut-scanner', to discover supported devices, both local and remote. nut-scanner will help to ease the configuration step, and power infrastructure discovery. This development, sponsored by Eaton, supports the following methods: * USB, * SNMP, * XML/HTTP (from Eaton), * NUT servers, using the classic connect or Avahi / mDNS methods. IPMI support will be added in the next release. A separate library, called 'libnutscan', is also available to provide these feature. Future NUT releases will provides binding for the supported languages (Perl, Python and Java). - NUT now provides a Java interface called 'jNut'. This development, sponsored by Eaton, is currently limited to the client interface. But it will be broaden to device discovery and configuration in the future. For more info, refer to nut/scripts/java/README, or the developer guide (chapter 'Creating new client'). Javadoc documentation is also provided, along with Java archives (.jar) in the Download section. - support for new devices: Eaton 3S ; Cyber Power Systems CP1000AVRLCD ; various APC models equiped with APC AP9618 management card, including APC Smart-UPS RT XL ; Orvaldi 750 / 900SP ; POWEREX VI 1000 LED ; PowerWalker VI 850 LCD ; SVEN Power Pro+ series (USB ID ffff:0000). - A regression has been fixed in udev rules file. This previously caused permission issues to owners of some USB devices. - Avahi support has been added, for NUT mDNS publication, through a static service file (nut/scripts/avahi/nut.service). - usbhid-ups has had Eaton completion: some features have been improved, such as 'output.voltage.nominal' ; 3S Eco control support has been added, along with battery.runtime.low and end of battery life (life cycle monitoring) support ; new measurements for 5 PX are also supported now (outlet power factor, power, real power and current). - apcsmart has been updated to support more variables and features ; the previous driver is however still available as 'apcsmart-old', in case of issues. - bcmxcp now supports per outlet startup and shutdown delays setting ; shutdown delay is also used, when available, for outlet.n.shutdown.return instead of the default 3 seconds. - snmp-ups.c has a new initialization method, that uses sysObjectID, which is a pointer to the prefered MIB of the device, to detect supported devices. This speeds up even more init stage and should render void the use of 'mib' option. SNMP v3 session initialisation has also been fixed, and Eaton PDU support has been completed. - Initial support has been added for systemd, the System and Service Manager from RedHat. - The chapter 'NUT configuration management with Augeas' of the developer guide has received some completion: a complete Python Augeas example code is now provided. - Finally, after years of dedication to NUT, Arjen de Korte is now retired. Sincere thanks to you Arjen from us all. --------------------------------------------------------------------------- Release notes for NUT 2.6.1 - what's new since 2.6.0: - the various recent USB regressions have been definitely fixed. - NUT now propose a variable to expose UPS efficiency (ups.efficiency). Eaton 5 PX already uses it. - the Perl module from Gabor Kiss (rewritten from Kit Peters') is now distributed with NUT source code. - support for new devices: Eaton Ellipse ECO, Powerware 9140, Eaton 5 PX, and ambient sensor on Eaton ePDU managed ; GE EP series ; Inform Sinus SS 210 ; IPAR Mini Energy ME 800 ; Mustek Yukai PowerMust 1000 USB ; Numeric 3000 SW ; SVEN Power Pro+ series (recent models) ; Vivaldi EA200 LED. - liebert-esp2: Improved Liebert ESP II support, including UPS shutdown (poweroff), 1 and 3-phase input and output variables, and most input / output / bypass / nominal variables. There is also a fix for the USB to serial cable (Farkas Levente and Spiros Ioannou). - powercom has improved PowerCom BNT 1500A and BNT-other support, along with driver documentation and code conformance to the NUT rules (Keven L. Ates). - apcsmart has more improved UPS poweroff support and options (Michal Soltys). - blazer has also seen some improvements. - usbhid-ups has completed a bit supported variables for APC and Eaton / MGE. - on the quality assurance side, Eaton has worked on fixing a few non conformances, like C++ style comments and warnings, using a newly developed verification tool (Prachi Gandhi). - fix remaining references to LIBSSL_LDFLAGS, instead of LIBSSL_LIBS, which cause unresolved symbol on libupsclient users (Fabrice Coutadeur). - the website has now a better support for Internet Explorer 6. - graphic illustrations, used for the Features page on the website Features and chapter of the user manual, have been refreshed (courtesy of Eaton). - more bugfixes, cleanup and improvements, on both source code and documentation. --------------------------------------------------------------------------- Release notes for NUT 2.6.0 - what's new since 2.4.3: - the main focus of this release is the complete documentation revamping, using AsciiDoc. This includes a new website, user manual, developer guide, packager guide and manual pages, available in various formats (single and multiple pages HTML, and PDF at the moment). Be sure to check the --with-doc configure option help, and docs/configure.txt for more information. - Add Augeas support, to provide easy NUT configuration management, through tools and development APIs. For more information, refer to the developer guide, or scripts/augeas/README in the source directory. - support for new devices: APC 5G; Eaton PowerWare 5119 RM (smart mode using upscode2 driver), Eaton Best Ferrups (using older ConnectUPS card), Eaton 9395 (serial interface), Eaton ConnectUPS X / BD / E Slot; HP T1000 INTL, HP T1500 INTL, HP T750 G2, HP R1500 G2 INTL; iDowell iBox UPS; Tripp Lite SmartOnline SU1000XLA, Tripp Lite Smart1000LCD, and some more USB/HID devices IDs; CyberPower CP1500AVRLCD and CP1350AVRLCD; PowerWalker Line-Interactive VI 1400 ; Rocketfish RF-1000VA / RF-1025VA. - usbhid-ups has better support for shutting down APC SmartUPS RM series, and finally fix the "buffer size" issue, which was breaking some devices data retrieval, or truncating some data on others. - snmp-ups now support SNMP v3 and its security parameters. IETF MIB support has also been extended. - fix dummy-ups simulation driver status handling bug, and add the capability to remove exposed variables on the fly. - the belkin driver now support control commands and status reporting for beeper and battery test. - the powerpanel driver supports more older CyberPower units. - mge-utalk, upscode2, blazer and liebert-esp2 have also received some care, and been improved. - NUT-Monitor and the PyNUT client module have been updated to 1.3, adding more features like automatic connection to the first local device and i18n support. - improve configure time dependencies checking and processing. - improve older Unix systems support (HP-UX, Aix, ...) for missing functions. - refresh and improve USB helper files (udev and UPower). - more generation automation: the ChangeLog file is now generated automatically at distribution time, along with the files needed for the website hardware compatibility list. - SSL support has also received some improvements. - tcp-wrapper now allows hostnames in /etc/hosts.allow too (not only IPv4 and/or IPv6 addresses). - many bugfixes, cleanup and improvements. --------------------------------------------------------------------------- Release notes for NUT 2.4.3 - what's new since 2.4.2: - this is a bugfix release that only solves the regression on IPv6 activation. --------------------------------------------------------------------------- Release notes for NUT 2.4.2 - what's new since 2.4.1: - the general USB support has been vastly improved, including many bug fixes, better OS support, new features and devices. - NUT now talks to Solar Controller Devices with the new ivtscd driver. - the snmp-ups driver supports more PDU, with a smaller disk footprint. - apcsmart supports more older SmartUPS and Matrix units. - the bestfortress driver is resurrected. - the virtual driver has been renamed to 'clone'. - the netxml-ups driver has received some care. - various debugging and development improvements have been done, around driver output; dummy-ups with more interaction and scripting and the device-recorder.sh script. - the build system has received many bugfixes and improvements. - the UPower (previously known as DeviceKit-power) rules file is now generated by NUT. - support for new devices: Apollo 1000A and 1000F; various Baytech RPC; old Best Power Fortress; Cyber Power Systems PR3000E, CP 1500C and OR2200LCDRM2U; all the new Dell UPS range (serial, USB and network); Eaton E Series NV and DX UPS, and Powerware 9130; older HP T500 and T750, newer T750 INTL (USB) and R1500 G2 (serial); Inform Informer Compact 1000VA; many serial and USB devices from Ippon, like Back Comfo Pro, Smart Power Pro and Smart Winner; IVT SCD series; Liebert GXT2-3000RT230 and PowerSure PSA; Mustek PowerMust 424 / 636 / 848 USB; all new PowerCOM USB devices with HID PDC interface; Tripp-Lite INTERNETOFFICE700, SMART700USB and ECO550UPS; UPSonic DS-800 (USB). --------------------------------------------------------------------------- Release notes for NUT 2.4.1 - what's new since 2.4.0: - the microdowell driver has appeared to support various MicroDowell Enterprise units (see the "new devices" list below). - support for new devices: MicroDowell Enterprise B8, B10, N8, N11, N15, N20, N22, N30, N40, N50, N60 and HiBox ST. - NUT-Monitor now better handles the ups.status field, and has switched to version 1.1. - the situation of the build toolchain has been fixed, with regard to the "make clean" target and the wrongly removed generated USB files. This brokes further configure call. --------------------------------------------------------------------------- Release notes for NUT 2.4.0 - what's new since 2.2.2: - preliminary support for Power Distribution Units (PDUs): NUT now support PDUs, either natively (ie using NUT snmp-ups driver), or through a binding to the Powerman daemon. The list of supported PDUs is already quite long, including: Eaton ePDUs (Managed and Monitored), some Aphel models, some Raritan PDUs, and the whole list of Powerman supported devices: http://powerman.sourceforge.net/supported.html - support for new devices: the various PDUs cited above, Chloride Desk Power 650, Cyber Power Systems Value 400E/600E/800E (USB models), Delta GES602N, Digitus DN-170020, the whole Eaton ranges (mostly composed of MGE Office Protection Systems and Powerware units) including BladeUPS, Forza Power Technologies SL-1001, HP PowerTrust 2997A, HP R/T 2200 G2, Infosec XP 1000 and XP 500, Ippon Back Power Pro (serial and USB), Kebo 1200D/D Series, Liebert PowerSure Personal XT, MGE Office Protection Systems Protection Station, Neus 400va and 600va, Phasak 400VA and 600VA, Plexus 500VA, Powercom Black Knight PRO / King PRO and Imperial, PowerKinetics BlackOut Buster, Sweex 1000 USB, UNITEK Alpha 500, WinPower CPM-800. - NUT now embeds Python client support through the PyNUTClient module and the NUT-Monitor application. Both are from David Goncalves, and are still available from http://www.lestat.st. For more information, refer to scripts/python/README. - the dummy-ups driver now support a "repeater" mode. This allows it to act as a NUT client, and to forward data. This can be useful for supervision and load sharing purposes. - tcp-wrappers support has been added to the upsd server, to grant users access by source IP for commands that require to be logged into the server. This replaces the previous internal implementation (ACL in upsd.conf). - the nut.conf file has been introduced to standardize startup configuration across the various systems. - NUT now ships a bash completion function for 'upsc' command (scripts/misc/nut.bash_completion). Simply copy it to /etc/bash_completion.d - many internal changes to improve maintenability, while lowering the maintenance cost (thus allowing developers to focus on what matters: the code!). Examples of this are: - the USB information automatic extraction to generate the various USB helper files, - the upsdrv_info_t structure to track more driver information, and remove the need for the upsdrv_banner() function - common USB code refactoring, as it is done for the serial functions. - tons of bugfixes, cleanup and improvements to make NUT stronger than ever! --------------------------------------------------------------------------- Release notes for NUT 2.2.2 - what's new since 2.2.1: - support for new devices: APC BACK-UPS XS LCD, Atlantis Land, Mustek Powermust Office 650, Oneac XAU models, Powerware PW5115 and PW9120 (USB), Nitram Elite 2005 - Integrated Power Management (NUT HAL integration) has reached a major milestone: it is now the most advanced UPS integration into Power Management layer known in existing OSs. It has received many corrections and improvements, and allows to PowerOff the UPS at the end of a power cycle (which is the most important feature, not supported on other systems). The various files are now installed into the correct location. - the usbhid-ups driver has received attention. Most notably, the shutdown handling has been reworked, and support for MGE UPS SYSTEMS 3 phases units has been added. - snmp-ups now supports MGE* Environment Sensor (ref 66 846). The ambient.temperature reporting has also been fixed for units other than APC. - the netxml-ups driver has appeared to support MGE* network HTTP/XML cards. - NUT now distributes by default the shared version of libupsclient (version 1.0.0), and use this for the provided clients (upsmon, upsc, upsrw, upscmd). This is part of an effort to reduce NUT's footprint, both on disk and in memory. - powerpanel has reach a new step toward the replacement of nitram and cpsups drivers. The final step is scheduled for NUT 2.4. - many changes, cleanup and fixes to the NUT core and various drivers. --------------------------------------------------------------------------- Release notes for NUT 2.2.1 - what's new since 2.2.0: - support for new devices: all MGE Office Protection Systems units, Advice TopGuard 2000, Belkin F6H375-USB, Dynamix UPS1700D, Effekta RM2000MH, Jageson Technology Jasuny USPS, Powercom SMK-1500A and SXL-1500A, PowerWalker Line-Interactive VI 400/800 and 600, Powerware 9110, UNITEK Alpha 2600, UPSonic CXR1000, some vintage serial APC UPSs. - the usbhid-ups driver has been improved, and fixed in many areas, through a backport of the development (trunk) version. - the udev rules, for Linux hotplug support of the USB UPSs, has been updated to support kernel newer than 2.6.22. - the megatec and megatec_usb drivers have also been backported from the development (trunk) version. - the client development files have also received some care: the upsclient pkg-config file has been fixed, and the upsclient.h file allows older NUT clients to continue using the UPSCONN structure. --------------------------------------------------------------------------- Release notes for NUT 2.2.0 - what's new since 2.0.5: - The new build infrastructure, using automake, is now used. This has major impact on the compilation and installation procedures, and thus on the NUT packaging. For more information, refer to UPGRADING and packaging/debian/ for an example of migration. - NUT now provides support for FreeDesktop Hardware Abstraction Layer (HAL) which brings full Plug And Play experience to USB UPS owners. For more information, refer to docs/nut-hal.txt. - support for new devices: Ablerex 625L, ActivePower 400VA, 2000VA; Belkin Home Office F6H350-SER, F6H500-SER, F6H650-SER; Belkin Office Series F6C550-AVR; Belkin Universal UPS F6C100-UNV (USB), F6C1100-UNV (USB), F6C1200-UNV (USB), F6H350deUNV (serial), F6H350ukUNV (serial), F6H650ukUNV (serial); Compaq R3000h; Cyber Power Systems PR2200; Dynex DX-800U; Geek Squad GS1285U; Krauler UP-M500VA; Mecer ME-2000; MGE UPS SYSTEMS Ellipse MAX; Online Zinto D; PowerTech SMK-800; SVEN Power Pro+ series, Power Smart RM 2000; Tripp-Lite SmartOnline SU1500RTXL2ua, smart2200RMXL2U. - added IPv6 support, - the newmge-shut driver has appeared. This one uses the same HID core as usbhid-ups, but communicate over a serial link. It will eventually replace the current mge-shut driver. - client commands (upsc, upsrw and upscmd): hostname is now optional, and defaults to "localhost" - many drivers have been improved and have received bug fixes: powerpanel, megatec, megatec_usb, safenet, tripplite_usb, gamatronic, - the hotplug and udev scripts, in charge of setting the right permissions on the USB devices, are now installed automatically when appropriate. - more generally, the NUT core and documentation, including the manpages, have been improved and updated. --------------------------------------------------------------------------- Release notes for NUT 2.0.5 - what's new since 2.0.4: This release is a backport of the development version. Many changes have already been backported previously. Thus it is more a synchronisation release, though it includes many bugfixes and support for new models. - support for new devices: APC Smart-UPS with 6TI firmware; Belkin Small Enterprise F6C1500-TW-RK; Compaq R3000 XR, R5500 XR; Cyber Power 550SL, 725SL, 685AVR, 800AVR, 1200AVR, AE550; Eltek; Inform GUARD; Microsol Rhino; Opti-UPS PowerES 420E; PowerMan RealSmart, BackPro; Powerware PW9315 3-phase; SOLA 305; Tripp-Lite SMART550USB, SMART2200RMXL2U, OMNI1000LCD, OMNI900LCD, OMNI650LCD, 1500 LCD, AVR550U; Viewsonic PowerES 420E. - bcmxcp: added 3-phase support - megatec: better hardware support, more instant commands - mge-hid: support more instant commands - newhidups: fixed APC and Tripp Lite bugs, various memory bugs, improved report buffering, improved Solaris support, added '-x explore' option for easy diagnosis of new devices - solis: shutdown programming, support new cables, Solaris support - tripplite_usb: updated SMARTPRO support, fixed OL/OB reporting, better error handling, some memory bugs - new dummy-ups driver simulator - added HTML interface for access to CGI scripts --------------------------------------------------------------------------- Release notes for NUT 2.0.4 - what's new since 2.0.3: - The newhidups critical bug (segmentation fault) has been fixed. It has also received some more care, like buxfixes and new models support and enhancement for Solaris. [Peter Selinger and Arnaud Quette] - A bug has been fixed in NUT core to support resuming from suspend-to-disk. This should also fix other similar issues, like time synchronisation through the NTP - Network Time Protocol. [Arjen de Korte] - The mge-shut driver now better detects the Low Battery status, support new models and fixes some wrong status and data. It also fixes some issue where the UPS wasn't restarting (refer to mge-shut manpage). [Arnaud Quette] - The genericups custom configuration through ups.conf is working again [Arjen de Korte] - The genericups driver type 22 also support CyberPower 725SL (and maybe others SL models) [David Kaufman] - The new megatec driver, which will replace a bunch of drivers by nut 2.2 (refer to docs/megatec.txt and UPGRADING) has been backported from the trunk (Development tree). The powermust driver has also received some attention. [Carlos Rodrigues] - The new rhino driver was added to support Microsol Rhino UPS hardware The solis has also been improved for solaris compatibility, and internal / external shutdown programming. solis can now save external shutdown programming to ups, and support new cables for solis 3 [Silvino B. Magalhães] - Several fixes and improvements have been made to upsrw, upsset, cpsups, tripplite_usb and the FAQ. [Arjen de Korte and Charles Lepple] --------------------------------------------------------------------------- Release notes for NUT 2.0.3 - what's new since 2.0.2: - The recent and major newhidups changes have been backported from the Development tree. It now: - supports models from MGE UPS SYSTEMS, APC and Belkin. Mustek and Unitek units are also recognized for development purpose, - handles better device reopening, after a disconnection, - handles multiple devices, with several parameters to find the right UPS. [Peter Selinger, Charles Lepple and Arnaud Quette] - The bcmxcp_usb driver has been added to support Powerware USB units. [Wolfgang Ocker and Kjell Claesson] - The tripplite_usb driver has been added to support Tripp Lite USB units. [Charles Lepple] - The sec driver is back as gamatronic [Gamatronic, Nadav Moskovitch] - The genericups driver has received official care from Gamatronic to add support for the Gamatronic UPS with alarm interface. [Gamatronic, Nadav Moskovitch] - The powermust driver now supports Soyntec Sekury C 500 and C 800 units. [Hanno Borns] - The mge-shut driver has received a bit of attention too, and enhance ups.model retrieval for some specific case (release 0.65) - The drivers don't change to the "statepath" directory anymore at initialisation time if called using -k. This avoid unneeded failure to poweroff the UPS if /var is already unmounted. [Gaspar Bakos] - The belkinunv driver now supports Belkin F6C1100-UNV [Dave Breiland] - The isbmex driver has been upgraded to version 0.05, which fixes various errors in formulas, add shutdown capability and revert back baudrate to B9600 (instead of B2400), as it broke the communication [Ricardo Martinezgarza] - The support of Sysgration UPGUARDS Pro650 in fentonups has been fixed [Simon J. Rowe] - The packaging files for Red Hat have received various fixes [Thomas Jarosch] - The solis driver has been fixed to avoid a naming colision and compile on Solaris [Paweł Kierdelewicz] - The snmp-ups driver has corrected the problem when exposing certain time data. --------------------------------------------------------------------------- Release notes for NUT 2.0.2 - what's new since 2.0.1: - the newhidups USB driver has been improved a lot and is no more experimental. It also now has a basic APC support, which will soon replace the legacy hidups driver. - The mge-utalk driver has improved its support for old units. - The mge-shut driver has been improved for restart/shutdown sequences which was previously blocking the serial port. - The general MGE support has been added Pulsar EXtreme C / EX RT, Comet EX RT, Pulsar SV, Pulsar PSX, Ellipse Office and NOVA AVR USB. - The genericups driver now supports Generic RUPS 2000, AEC MiniGuard UPS 700 (using Megatec M2501 cable), and Powerware 3110. [Nick Barnes, Paul Andreassen] - The powermust driver now supports SquareOne Power QP1000, Mustek PowerMust 1400VA Plus and 2000VA USB. [Carlos Rodrigues] - The fentonups driver has been enhanced and now supports Sysgration UPGUARDS Pro650. [Michel Bouissou, Simon J. Rowe] - The cpsups driver now supports MicroDowell B.Box BP 500/750/1000/1500. [Armin Diehl] - The snmp-ups driver now supports Socomec SNMP devices (Netvision MIB), and Powerware ConnectUPS SNMP cards. [Thanos Chatziathanassiou, Olli Salvia] - The bcmxcp driver is back with support for Powerware UPSs. [Tore Øpetveit, Kjell Claesson] - The cyberpower driver now supports CyberPower 1000AVR. [Dave Huang] - The new solis driver supports Microsol units: Solis 1.0, 1.5, 2.0 and 3.0. [Silvino B. Magalhaes] - The apcsmart driver has fixed APC600 support. - The etapro driver fixes brokeness due to ser_get_line use [Marek Michalkiewicz] - The new upscode2 driver supports Fiskars, Compaq and Powerware devices. [Niels Baggesen, Havard Lygre] - The tripplite driver has fixed a battery charge bug [Cedric Tefft] --------------------------------------------------------------------------- Release notes for NUT 2.0.1 - what's new since 2.0.0: - The bestuferrups driver has been forked into the new bestfcom driver which has better handling of the inverter status alarm messages and more. [Kent Hill] - Mustek UPS support returns with two drivers which have overlapping coverage: mustek and powermust. [powermust: Carlos Rodrigues, mustek: Martin Hajduch] - Additional CyberPower Systems hardware is supported with the new cpsups driver. Three recognized models are the CPS1500AVR, CPS1100VA, and OP500TE. [Walt Holman, Brad Sawatzky] - The genericups driver can now generate staleness warnings in specific cases where the UPS provides a way to test for its presence. See the "CON" setting in ups.conf for more details. [stan / saticed.me.uk] - Documentation for monitoring a Back-UPS RS 500 on a system without USB ports has been added to the cables directory. [Martin Edlman] - The everups driver now supports types 73-76 (NET 700/1000/1400/500-DPC) [hunter] - The new metasys driver supports Meta System models: Line, HF Millennium, HF Top Line, ECO Network, ECO, Ally HF, Megaline [BlaXwan] - The ippon driver now allows user-defined settings for the delay before switching off, and the delay before powering on. [Yuri Elizarov] - The victronups driver is now at version 0.1.9, which adds many instant commands: calibration control, battery and front panel tests, and bypass control. [Gert Lynge] - The tripplite driver has recieved a major overhaul to bring it up to working condition for the 2.0 tree, including code cleanups, several new variables, commands, and user-definable parameters. See ChangeLog for more. [Nicholas J Kain] - The mge-utalk driver has been upgraded to version 0.81, which fixes the lack of read-write variables and loss of sync on models which don't support restoring settings. [Arnaud Quette] - The Micro Ferrups model RE is now supported by the bestuferrups driver. The driver will also now read the ambient temperature and will no longer constantly report the data as stale. [Tim Thompson] - The fentonups driver's init sequence has been reworked to work better with some hardware, including a fix to the parser code. [MLH] - A workaround has been added to the hidups driver to avoid variables which are stuck by calling HIDIOCINITREPORT in every poll. [Stuart D. Gathman] - SOLA 610 UPS hardware and others which do not support the ID command may now be monitored by the bestups driver after forcing ID= in ups.conf. [Jason White] - "pollinterval" is now available via driver.parameter for consistency. [Arnaud Quette] - The mge-shut and newhidups drivers, along with the supporting hidparser/libhid code have received many updates, including lowering USB bandwidth consumption, driver unbinding (only in Linux), code cleanups, and more which can be seen in the ChangeLog file. [Arnaud Quette] - The fentonups driver now recognizes several more Megatec protocol units: SuperPower HP360, Hope-550 [Denis Zaika] Unitek Alpha 1000is [Antoine Cuvellard] - Some variables like uc_sigmask were renamed to avoid clashes with symbols on systems like HP/UX. - All man pages have been reworked to switch literal "-" characters to hyphens or "\-" as appropriate. [Shaul Karl] - upssched's CANCEL events were broken following the change to text-based socket messages in 1.5 and have been fixed. [Steven Schoch] - Calls to varargs functions with raw strings from the config files without an intervening "%s" have been fixed in upsmon, upssched, snmp-ups and upsd. [Ulf Harnhammar] --------------------------------------------------------------------------- Release notes for NUT 2.0.0 - what's new since 1.4.x: - The new naming scheme for variables and commands (introduced in 1.4) is now mandatory. The 1.4 tree supported both the old (STATUS) and the new (ups.status) as a transitional release, and now that time is over. This means that 2.0 is generally smaller than 1.4 code, since the interim compatibility hacks have been removed. - New serial handling code has been added, with greatly simplified operations. The old mess involving repeated calls to sigaction, alarm, and read has been condensed to a select-read loop. This change allows drivers which don't do any serial communications at all (hidups, snmp-ups) to drop that baggage, so they are a bit smaller when compiled. - The drivers now recognize "chroot=' and 'user=' in the global section of ups.conf. This means you don't have to use -r and -u when starting upsdrvctl. - upsmon now supports the -K argument to check for the presence of the POWERDOWNFLAG file. If it exists and contains the magic string, then upsmon will exit(EXIT_SUCCESS). Otherwise, it will exit(EXIT_FAILURE). This feature can be used to simplify shutdown scripts, since now you don't have to keep the script in sync with the upsmon.conf. - Many small things like signed value comparisons, int vs. size_t and proper use of const/struct were fixed throughout the source. These were mostly for correctness, but a few potential bugs involving very big or very small numbers were fixed at the same time. - The access control system in upsd.conf has been reworked and simplified. Since access levels have become meaningless in recent releases, the new system is just ACCEPT or REJECT . If you are upgrading from a previous version of the software, you will have to edit your upsd.conf to use this method. See the UPGRADING file for more details. - The build process now halts when make fails in one of the subdirectories. [Petter Reinholdtsen, Charles Lepple] - Helper data for using upsclient via pkgconfig is now created if pkgconfig is detected when configure runs. [Arnaud Quette] - The polling interval in drivers may now be set with 'pollinterval' in ups.conf. [Gabriel Faber] - Blazer UPS equipment is now supported with the blazer driver. [Phil Hutton] - Energizer USB UPS hardware is now supported on Linux with a new experimental driver. [Viktor T. Toth] - The newhidups driver has been merged as the first step towards portable USB UPS support. This will eventually replace the old Linux-only hidups driver. The newhidups driver is tagged experimental since it is under active development. [Arnaud Quette, Charles Lepple] - The newapc driver has been renamed to apcsmart, replacing the old driver with that name. If you used the newapc driver, be sure to delete the old binary and fix your ups.conf. - The apcsmart driver now supports asynchronous notification data from the hardware, which means it can wake up as soon as something happens. This affects the OL/OB/LB/RB data in ups.status, and generally reduces the latency in dispatching status changes by a few seconds. - The apcsmart driver can now support quirky hardware which does not provide the usual listing of valid command characters. This feature is necessary to monitor new models like the APC CS 350 and old ones like the Matrix 5000. It also now has sdtype=4 to handle the strange shutdown behavior on the CS series. - The belkin driver now works around broken firmware version 001, avoiding a lengthy delay at startup. It also implements the shutdown sequence differently, and should actually work on more hardware now. - The bestups driver has been slowed down to play nicer with the hardware, and is much more reliable as a result. Among other things, it should always detect the UPS on the first try, meaning no more "dot dot dot" when it starts. - The cyberpower driver is no longer tagged experimental, and now supports powering off the load. It also supports battery tests via instcmds. - Effekta MT 2000 RM hardware is now supported by the fentonups driver. [christoph moar] - The new safenet driver supports UPS hardware that uses the protocol of the same name. This includes models from many manufacturers, including Fairstone, Fenton, Gemini, Powerwell, Repotec, Soltec and Sweex. See the README or driver.list for the full details. [Arjen de Korte] - The genericups driver now has type 20 to monitor the Powerware 5119 RM. See http://lists.exploits.org/ups/Oct2003/00052.html. [Daniel Thompson] - The belkinunv driver has been added to allow monitoring Belkin Universal UPS hardware. [Peter Selinger] - Cyber Power Systems 1100AVR hardware which has a different protocol than the existing binary type (supported by 'cyberpower') is now supported by the experimental cyberpower1100 driver. [Walt Holman] - upsdrvctl now returns success or failure information in the exit code. Any failure during a requested operation will result in a nonzero value (specifically EXIT_FAILURE). --------------------------------------------------------------------------- Release notes for NUT 1.4.0 - what's new since 1.2.x: - The drivers and upsd now communicate over Unix domain sockets instead of state files, shared memory, or state files with mmap. This change makes many things possible, including the new dynamic variable and command naming scheme described below. There is a new development tool called sockdebug in the server directory for debugging driver-server communications on the sockets. - The old static variable scheme has been replaced by a new dynamic implementation. Vague names have been turned into meaningful names that fit into an organized system. UTILITY is now input.voltage. OUTVOLT is now output.voltage. This also applies to the names of instant commands. BTEST1 is test.battery.start, and BTEST0 is test.battery.stop. The old names are still supported for compatibility with older clients. This compatibility mode will be maintained throughout the 1.4 series, and will be gone by the release of 2.0. Users with older clients are encouraged to upgrade their software during this time. - The network protocol has been expanded to handle these new names. Older functions which only apply to the old names will continue to be supported through the 1.4 series. - The drivers and server (upsd) can now change their user ids and chroot themselves with the new -u and -r arguments. This lets you create a "chroot jail" with the bare minimum components. This technique is used to provide a higher degree of security. If someone exploited upsd to get a shell somehow, they would be stuck in the jail. - upssched now explicitly confirms reception of timer commands before exiting. This was done to avoid a race where one process would exit right when another one was starting. The second one would believe its command had been handled when it had been lost. - upslog has been reworked to use standard getopt parsing to provide the monitoring settings. The old way of specifying arguments is still supported for backwards compatibility. upslog has also been changed to only parse the format string once, rather than doing it every time through the loop. This should provide a minuscule drop in CPU utilization. - Usernames are now required in upsmon and upsd. This means that you must add a username to your MONITOR lines in upsmon.conf and then create a matching user in upsd.users. Installations from the 1.2 era probably already use usernames, so this mostly affects those from 1.0 and before. - Drivers are now pinged regularly by upsd when they aren't posting updates about the UPS status. This provides another check in the data validation process. If upsd fails to get a response within a few seconds, the UPS will be marked stale. - A few minor memory leaks were discovered with valgrind and squashed. - upsstats now reuses connections to upsd when cycling through multiple entries in the hosts.conf. This makes things a bit faster and avoids some of the noise in the syslog. This only applies to entries that are adjacent. To take advantage of this feature, you may have to rearrange them. MONITOR ups-1@host-1 ... MONITOR ups-1@host-2 ... MONITOR ups-2@host-2 ... MONITOR ups-3@host-3 ... Connection reuse for nonadjacent entries may be considered in the future. - upsd now warns about insecure configuration files at startup. These files (upsd.conf, upsd.users, and the certfile) should only be readable by upsd. Never make them world-readable. - The programs no longer print "shutting down" when they are just exiting. This was changed to avoid confusion about the term, since "shutting down" has a special meaning in UPS software. - Signal handlers no longer do any significant amount of work. Some of the programs used to do numerous things in there, raising concerns about reentrancy. They now set flags and allow the main loop to do the actual work from there. - A bug in upsmon where NOTIFYFLAG settings could be ignored was fixed. - Group handling has been changed. configure no longer accepts --with-group, and the programs no longer setgid() to a hardcoded value. They now setgid() to the primary group of whatever the user value may be. This may be compiled in with --with-user as before, and many programs accept -u to override it at runtime. - The state path is no longer created during 'make install'. Users are now expected to create it themselves. This removes a lot of evil complexity from the build and install sequences. - upsd no longer implements the DROP access command, as it could confuse the clients by getting them out of sync. DROP is now implemented as DENY, which sends an error message. If you use DROP, you should change it to DENY rather than relying on this compatibility measure. - The belkin driver no longer reports OFF and OL at the same time. - The bestups driver no longer sleeps during polls, which makes it more responsive to things like instant commands. - The cyberpower driver now has much better hardware detection code and no longer freezes at startup under some conditions. It also now supports the shutdown function. Instant commands for shutdowns and battery tests were also added. - The dummyups testing driver has been removed. The dummycons testing driver can do everything that dummyups once did and much more. dummycons is also now built by default for easier testing. - The newapc driver has been reworked to take advantage of the new internal driver state functions. Some variables without an obvious purpose were dropped. - The newapc driver now sends all five bytes when using sdtype 1. Previously it didn't send the entire string, and it didn't work. [Don Lewis] - The hidups driver has been expanded to allow for setting variables, a shutdown sequence, and more. [Arnaud Quette] - The mge-utalk driver had trouble establishing communications in some cases due to the RTS line being set. This has been fixed. The mge-shut driver has been added to the tree, and has replaced the older mge-ellipse driver. [Arnaud Quette, Philippe Marzouk] - Outlet-level control has been defined in the variable tree, and will be added to drivers where the hardware supports it. This can be used to shut down some components earlier than others to prolong your runtime on battery. This is supported in the mge-shut driver now, and may show up in others before long. [Arnaud Quette] - KIN-2200AP hardware is now recognized by the powercom driver. This change may also support other KIN-xxxxAP equipment. [Preston A. Elder] - The 1.1kVA UPS is now supported by the bestuferrups driver. This driver was also changed to allow easy addition of more models in the future. [Bob Apodaca] - The fentonups driver can now handle devices which implement the "I" detection differently, and now supports the Giant/WELI 500 as a result. [Joon Guillen] - The serial number of the UPS being monitored can now be specified with serial= in ups.conf in the genericups driver. [Shaul Karl] - The newapc driver now sends ESC to break out of menus when the initial detection fails. Some new APC models have interactive menus on the serial port, and the driver couldn't handle them before. - The snmp-ups driver now reports ambient temperature and humidity data for APC equipment. It also now supports the shutdown.reboot and shutdown.reboot.graceful commands. [Dmitry Frolov] - The list of supported variables and commands in the snmp-ups driver has been expanded. [Arnaud Quette, J.W. Hoogervorst] - Various drivers now report bypass mode with the BYP status word. [Arnaud Quette] - Energy Sistem equipment is now supported with the esupssmart driver. [Antonio Trujillo Coronado] - The Tripp-Lite SU series (SmartOnline) is supported with the new tripplitesu driver. [Allan Hessenflow] - The HP PowerTrust A2994A is now recognized by the hp driver. [Jan Sporbeck] - Many drivers were cleaned up to perform basic sanity checks on the status data before using it. - An explicit cleanup function has been added to the driver core to ensure that all dynamic resources are freed before exiting. This is part of the larger process to check for memory leaks and other bad things. [Arnaud Quette] - upsd now provides variable descriptions from an auxiliary file. This file is optional, which allows for a smaller memory footprint. It can also be edited for localization or other customizations. - upsimage and upsstats can now render BATTVOLT data. [Andrew R. Ghali] - String handling has been cleaned up throughout the tree. Calls to functions like strcpy and strcat were either replaced with other (range-checking) functions or were rewritten to avoid it. - Many compile-time defaults may now be overridden at runtime. In the environment NUT_CONFPATH and NUT_STATEPATH may be used. upsdrvctl has been changed to execve to pass these along to the drivers. ups.conf now supports driverpath=, and upsd.conf supports DATAPATH. [Bryan Henderson] - The configure --with-gd switches now actually do something useful when gd has been installed outside the default search directories. [Patrik Schindler] - The inline keyword is now handled properly on systems which do not support it or have it specified as another name. This was breaking compiles on some systems. [Petter Reinholdtsen] --------------------------------------------------------------------------- Release notes for NUT 1.2.2 - what's new since 1.2.1: - The snmp-ups driver has been upgraded and expanded. It now supports multiple MIBs, meaning it can handle RFC 1628, APCC, and MGE equipment. You can pick the right one with "mibs=" in ups.conf. Support for setting variable and instant commands is also available. [Arnaud Quette and Dmitry Frolov] - The powernet driver has been upgraded. It now supports more variables, has cleaner logging, and may now be considered stable. [Dmitry Frolov] - The hidups driver now supports physical port IDs. This avoids most of the problems where the hiddev* names can jump around too easily. It will now stay in the same place as long as you keep it plugged into the same physical port. See the ChangeLog file for more details. [David Brownell] - The hidups driver now also supports the MFR variable on APC Back-UPS ES equipment. [Jonathan A. Davis] - The sms driver has been updated to version 0.70. [Marcio Gomes] - The bestups driver now recognizes Best Power Axxium Rackmount equipment. [Ales Casar] - The liebert driver now uses O_NONBLOCK, and should now work consistently on OpenBSD as a result. [Alex Cichowski] - The liebert driver also now uses debouncing logic on the status lines. It was possible to get false readings that would start a shutdown or just annoy users with excessive onbatt/online notify messages. The new code forces the status to settle down for 3 polls before accepting the new value. This means that very short power events may not be detected. The alternative is having your machine shut down just because it decided to wiggle over to OB LB for a few seconds. - upsmon has had the disconnect logic fixed so the "communications lost" (COMMBAD) notify will actually go out when the connection fails. [Steve Monett] - upssched now uses a lock file to prevent a race where two could start at the same time. The second upssched would "win", and the first one would be unreachable. This had the side-effect of not being able to cancel timers on the first one. If you use upssched, you must define the LOCKFN directive when upgrading to this version, or it will not work. [Gaspar Bakos] - The packaging and scripts for Red Hat systems have been updated. [Antonino Albanese] - upsd is now a bit more lenient about access levels in the 'numlogins' check, which is what caused the problem in upsmon (next item). - upsmon no longer gets stuck in slavesync() when upsd is configured to drop certain queries. This usually happened at the worst possible time: in the middle of a shutdown. [John David Garza] - The upsclient functions now do more sanity checking on data from upsd so a short read won't return garbage to the callers. - upsset now works properly with ENUM/VARTYPE values for multiple UPSes on a single upsd. [Dmitry Frolov] - Various portability fixes for building on SGI were applied. [Andrea Suatoni] - upsd no longer tries to reference a deleted client structure if the client disconnects at the wrong time. Previously, it tried to use that pointer after the sendback() function had already failed on write and deleted the client. This could cause upsd to segfault depending on what areas were accessed. [Patrik Schindler] --------------------------------------------------------------------------- Release notes for NUT 1.2.1 - what's new since 1.2.0: - The sms driver is back, with support for Microlink Manager III hardware. [Marcio Gomes] - Fideltronik Ares Series hardware is now supported as genericups type 19. [Tomek Orzechowski and Arkadiusz Mikiewicz] - The drivers no longer silently drop instant commands or set commands from upsd that happen to get fragmented in transit. [linux@horizon.com] - The old multilink driver is back with a new name: liebert. It supports Liebert UPStation GXE hardware with the contact-closure cable. This is currently an experimental driver as there is no way to power down the load. - configure now picks up the right flags for gd automatically if gd 2.0.8 or higher is installed. This greatly simplifies the CGI build process for most users. - Shutdowns on FreeBSD using the genericups driver should work again. [Petri Riihikallio] --------------------------------------------------------------------------- nut-2.7.2/compile0000755000175000017500000000727112277355125010647 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2009-10-06.20; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software # Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use `[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: nut-2.7.2/config.sub0000755000175000017500000010532712277406216011253 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-04-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nut-2.7.2/clients/0000755000175000017500000000000012324034433010770 500000000000000nut-2.7.2/clients/upscmd.c0000644000175000017500000001752212301203176012353 00000000000000/* upscmd - simple "client" to test instant commands via upsd Copyright (C) 2000 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut_platform.h" #include #include #include #include #include #include "upsclient.h" static char *upsname = NULL, *hostname = NULL; static UPSCONN_t *ups = NULL; struct list_t { char *name; struct list_t *next; }; static void usage(const char *prog) { printf("Network UPS Tools upscmd %s\n\n", UPS_VERSION); printf("usage: %s [-h]\n", prog); printf(" %s [-l ]\n", prog); printf(" %s [-u ] [-p ] []\n\n", prog); printf("Administration program to initiate instant commands on UPS hardware.\n"); printf("\n"); printf(" -h display this help text\n"); printf(" -l show available commands on UPS \n"); printf(" -u set username for command authentication\n"); printf(" -p set password for command authentication\n"); printf("\n"); printf(" UPS identifier - [@[:]]\n"); printf(" Valid instant command - test.panel.start, etc.\n"); printf(" [] Additional data for command - number of seconds, etc.\n"); } static void print_cmd(char *cmdname) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; query[0] = "CMDDESC"; query[1] = upsname; query[2] = cmdname; numq = 3; ret = upscli_get(ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) { printf("%s\n", cmdname); return; } /* CMDDESC */ printf("%s - %s\n", cmdname, answer[3]); } static void listcmds(void) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; struct list_t *lhead = NULL, *llast = NULL, *ltmp, *lnext; query[0] = "CMD"; query[1] = upsname; numq = 2; ret = upscli_list_start(ups, numq, query); if (ret < 0) { /* old upsd = no way to continue */ if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query"); } fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } while (upscli_list_next(ups, numq, query, &numa, &answer) == 1) { /* CMD */ if (numa < 3) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa); } /* we must first read the entire list of commands, before we can start reading the descriptions */ ltmp = xcalloc(1, sizeof(*ltmp)); ltmp->name = xstrdup(answer[2]); if (llast) { llast->next = ltmp; } else { lhead = ltmp; } llast = ltmp; } /* walk the list and try to get descriptions, freeing as we go */ printf("Instant commands supported on UPS [%s]:\n\n", upsname); for (ltmp = lhead; ltmp; ltmp = lnext) { lnext = ltmp->next; print_cmd(ltmp->name); free(ltmp->name); free(ltmp); } } static void do_cmd(char **argv, const int argc) { char buf[SMALLBUF]; if (argc > 1) { snprintf(buf, sizeof(buf), "INSTCMD %s %s %s\n", upsname, argv[0], argv[1]); } else { snprintf(buf, sizeof(buf), "INSTCMD %s %s\n", upsname, argv[0]); } if (upscli_sendline(ups, buf, strlen(buf)) < 0) { fatalx(EXIT_FAILURE, "Can't send instant command: %s", upscli_strerror(ups)); } if (upscli_readline(ups, buf, sizeof(buf)) < 0) { fatalx(EXIT_FAILURE, "Instant command failed: %s", upscli_strerror(ups)); } /* FUTURE: status cookies will tie in here */ if (strncmp(buf, "OK", 2) != 0) { fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf); } fprintf(stderr, "%s\n", buf); } static void clean_exit(void) { if (ups) { upscli_disconnect(ups); } free(upsname); free(hostname); free(ups); } int main(int argc, char **argv) { int i, ret, port; int have_un = 0, have_pw = 0, cmdlist = 0; char buf[SMALLBUF], username[SMALLBUF], password[SMALLBUF]; const char *prog = xbasename(argv[0]); while ((i = getopt(argc, argv, "+lhu:p:V")) != -1) { switch (i) { case 'l': cmdlist = 1; break; case 'u': snprintf(username, sizeof(username), "%s", optarg); have_un = 1; break; case 'p': snprintf(password, sizeof(password), "%s", optarg); have_pw = 1; break; case 'V': fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); case 'h': default: usage(prog); exit(EXIT_SUCCESS); } } argc -= optind; argv += optind; if (argc < 1) { usage(prog); exit(EXIT_SUCCESS); } /* be a good little client that cleans up after itself */ atexit(clean_exit); if (upscli_splitname(argv[0], &upsname, &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]"); } ups = xcalloc(1, sizeof(*ups)); if (upscli_connect(ups, hostname, port, 0) < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } if (cmdlist) { listcmds(); exit(EXIT_SUCCESS); } if (argc < 2) { usage(prog); exit(EXIT_SUCCESS); } /* also fallback for old command names */ if (!strchr(argv[1], '.')) { fatalx(EXIT_FAILURE, "Error: old command names are not supported"); } if (!have_un) { struct passwd *pw; memset(username, '\0', sizeof(username)); pw = getpwuid(getuid()); if (pw) { printf("Username (%s): ", pw->pw_name); } else { printf("Username: "); } if (!fgets(username, sizeof(username), stdin)) { fatalx(EXIT_FAILURE, "Error reading from stdin!"); } /* deal with that pesky newline */ if (strlen(username) > 1) { username[strlen(username) - 1] = '\0'; } else { if (!pw) { fatalx(EXIT_FAILURE, "No username available - even tried getpwuid"); } snprintf(username, sizeof(username), "%s", pw->pw_name); } } /* getpass leaks slightly - use -p when testing in valgrind */ if (!have_pw) { /* using getpass or getpass_r might not be a good idea here (marked obsolete in POSIX) */ char *pwtmp = GETPASS("Password: "); if (!pwtmp) { fatalx(EXIT_FAILURE, "getpass failed: %s", strerror(errno)); } snprintf(password, sizeof(password), "%s", pwtmp); } snprintf(buf, sizeof(buf), "USERNAME %s\n", username); if (upscli_sendline(ups, buf, strlen(buf)) < 0) { fatalx(EXIT_FAILURE, "Can't set username: %s", upscli_strerror(ups)); } ret = upscli_readline(ups, buf, sizeof(buf)); if (ret < 0) { if (upscli_upserror(ups) != UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Set username failed: %s", upscli_strerror(ups)); } fatalx(EXIT_FAILURE, "Set username failed due to an unknown command.\n" "You probably need to upgrade upsd."); } snprintf(buf, sizeof(buf), "PASSWORD %s\n", password); if (upscli_sendline(ups, buf, strlen(buf)) < 0) { fatalx(EXIT_FAILURE, "Can't set password: %s", upscli_strerror(ups)); } if (upscli_readline(ups, buf, sizeof(buf)) < 0) { fatalx(EXIT_FAILURE, "Set password failed: %s", upscli_strerror(ups)); } do_cmd(&argv[1], argc - 1); exit(EXIT_SUCCESS); } /* Formal do_upsconf_args implementation to satisfy linker on AIX */ #if (defined NUT_PLATFORM_AIX) void do_upsconf_args(char *upsname, char *var, char *val) { fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called"); } #endif /* end of #if (defined NUT_PLATFORM_AIX) */ nut-2.7.2/clients/nutclient.cpp0000644000175000017500000007601412303134465013434 00000000000000/* nutclient.cpp - nutclient C++ library implementation Copyright (C) 2012 Emilien Kia This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "nutclient.h" #include #include #include #include /* Windows/Linux Socket compatibility layer: */ /* Thanks to Benjamin Roux (http://broux.developpez.com/articles/c/sockets/) */ #ifdef WIN32 # include #else # include # include # include # include # include /* close */ # include /* gethostbyname */ # include # define INVALID_SOCKET -1 # define SOCKET_ERROR -1 # define closesocket(s) close(s) typedef int SOCKET; typedef struct sockaddr_in SOCKADDR_IN; typedef struct sockaddr SOCKADDR; typedef struct in_addr IN_ADDR; #endif /* WIN32 */ /* End of Windows/Linux Socket compatibility layer: */ /* Include nut common utility functions or define simple ones if not */ #ifdef HAVE_NUTCOMMON #include "common.h" #else /* HAVE_NUTCOMMON */ #include #include static inline void *xmalloc(size_t size){return malloc(size);} static inline void *xcalloc(size_t number, size_t size){return calloc(number, size);} static inline void *xrealloc(void *ptr, size_t size){return realloc(ptr, size);} static inline char *xstrdup(const char *string){return strdup(string);} #endif /* HAVE_NUTCOMMON */ namespace nut { SystemException::SystemException(): NutException(err()) { } std::string SystemException::err() { if(errno==0) return "Undefined system error"; else { std::stringstream str; str << "System error " << errno << ": " << strerror(errno); return str.str(); } } namespace internal { /** * Internal socket wrapper. * Provides only client socket functions. * * Implemented as separate internal class to easily hide plateform specificities. */ class Socket { public: Socket(); void connect(const std::string& host, int port)throw(nut::IOException); void disconnect(); bool isConnected()const; void setTimeout(long timeout); bool hasTimeout()const{return _tv.tv_sec>=0;} size_t read(void* buf, size_t sz)throw(nut::IOException); size_t write(const void* buf, size_t sz)throw(nut::IOException); std::string read()throw(nut::IOException); void write(const std::string& str)throw(nut::IOException); private: SOCKET _sock; struct timeval _tv; std::string _buffer; /* Received buffer, string because data should be text only. */ }; Socket::Socket(): _sock(INVALID_SOCKET), _tv() { _tv.tv_sec = -1; _tv.tv_usec = 0; } void Socket::setTimeout(long timeout) { _tv.tv_sec = timeout; } void Socket::connect(const std::string& host, int port)throw(nut::IOException) { int sock_fd; struct addrinfo hints, *res, *ai; char sport[NI_MAXSERV]; int v; fd_set wfds; int error; socklen_t error_size; long fd_flags; _sock = -1; if (host.empty()) { throw nut::UnknownHostException(); } snprintf(sport, sizeof(sport), "%hu", (unsigned short int)port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; while ((v = getaddrinfo(host.c_str(), sport, &hints, &res)) != 0) { switch (v) { case EAI_AGAIN: continue; case EAI_NONAME: throw nut::UnknownHostException(); case EAI_SYSTEM: throw nut::SystemException(); case EAI_MEMORY: throw nut::NutException("Out of memory"); default: throw nut::NutException("Unknown error"); } } for (ai = res; ai != NULL; ai = ai->ai_next) { sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock_fd < 0) { switch (errno) { case EAFNOSUPPORT: case EINVAL: break; default: throw nut::SystemException(); } continue; } /* non blocking connect */ if(hasTimeout()) { fd_flags = fcntl(sock_fd, F_GETFL); fd_flags |= O_NONBLOCK; fcntl(sock_fd, F_SETFL, fd_flags); } while ((v = ::connect(sock_fd, ai->ai_addr, ai->ai_addrlen)) < 0) { if(errno == EINPROGRESS) { FD_ZERO(&wfds); FD_SET(sock_fd, &wfds); select(sock_fd+1,NULL,&wfds,NULL, hasTimeout()?&_tv:NULL); if (FD_ISSET(sock_fd, &wfds)) { error_size = sizeof(error); getsockopt(sock_fd,SOL_SOCKET,SO_ERROR, &error,&error_size); if( error == 0) { /* connect successful */ v = 0; break; } errno = error; } else { /* Timeout */ v = -1; break; } } switch (errno) { case EAFNOSUPPORT: break; case EINTR: case EAGAIN: continue; default: // ups->upserror = UPSCLI_ERR_CONNFAILURE; // ups->syserrno = errno; break; } break; } if (v < 0) { close(sock_fd); continue; } /* switch back to blocking operation */ if(hasTimeout()) { fd_flags = fcntl(sock_fd, F_GETFL); fd_flags &= ~O_NONBLOCK; fcntl(sock_fd, F_SETFL, fd_flags); } _sock = sock_fd; // ups->upserror = 0; // ups->syserrno = 0; break; } freeaddrinfo(res); if (_sock < 0) { throw nut::IOException("Cannot connect to host"); } #ifdef OLD struct hostent *hostinfo = NULL; SOCKADDR_IN sin = { 0 }; hostinfo = ::gethostbyname(host.c_str()); if(hostinfo == NULL) /* Host doesnt exist */ { throw nut::UnknownHostException(); } // Create socket _sock = ::socket(PF_INET, SOCK_STREAM, 0); if(_sock == INVALID_SOCKET) { throw nut::IOException("Cannot create socket"); } // Connect sin.sin_addr = *(IN_ADDR *) hostinfo->h_addr; sin.sin_port = htons(port); sin.sin_family = AF_INET; if(::connect(_sock,(SOCKADDR *) &sin, sizeof(SOCKADDR)) == SOCKET_ERROR) { _sock = INVALID_SOCKET; throw nut::IOException("Cannot connect to host"); } #endif // OLD } void Socket::disconnect() { if(_sock != INVALID_SOCKET) { ::closesocket(_sock); _sock = INVALID_SOCKET; } _buffer.clear(); } bool Socket::isConnected()const { return _sock!=INVALID_SOCKET; } size_t Socket::read(void* buf, size_t sz)throw(nut::IOException) { if(!isConnected()) { throw nut::NotConnectedException(); } if(_tv.tv_sec>=0) { fd_set fds; FD_ZERO(&fds); FD_SET(_sock, &fds); int ret = select(_sock+1, &fds, NULL, NULL, &_tv); if (ret < 1) { throw nut::TimeoutException(); } } ssize_t res = ::read(_sock, buf, sz); if(res==-1) { disconnect(); throw nut::IOException("Error while reading on socket"); } return (size_t) res; } size_t Socket::write(const void* buf, size_t sz)throw(nut::IOException) { if(!isConnected()) { throw nut::NotConnectedException(); } if(_tv.tv_sec>=0) { fd_set fds; FD_ZERO(&fds); FD_SET(_sock, &fds); int ret = select(_sock+1, NULL, &fds, NULL, &_tv); if (ret < 1) { throw nut::TimeoutException(); } } ssize_t res = ::write(_sock, buf, sz); if(res==-1) { disconnect(); throw nut::IOException("Error while writing on socket"); } return (size_t) res; } std::string Socket::read()throw(nut::IOException) { std::string res; char buff[256]; while(true) { // Look at already read data in _buffer if(!_buffer.empty()) { size_t idx = _buffer.find('\n'); if(idx!=std::string::npos) { res += _buffer.substr(0, idx); _buffer.erase(0, idx+1); return res; } res += _buffer; } // Read new buffer size_t sz = read(&buff, 256); _buffer.assign(buff, sz); } } void Socket::write(const std::string& str)throw(nut::IOException) { // write(str.c_str(), str.size()); // write("\n", 1); std::string buff = str + "\n"; write(buff.c_str(), buff.size()); } }/* namespace internal */ /* * * Client implementation * */ Client::Client() { } Client::~Client() { } bool Client::hasDevice(const std::string& dev)throw(NutException) { std::set devs = getDeviceNames(); return devs.find(dev) != devs.end(); } Device Client::getDevice(const std::string& name)throw(NutException) { if(hasDevice(name)) return Device(this, name); else return Device(NULL, ""); } std::set Client::getDevices()throw(NutException) { std::set res; std::set devs = getDeviceNames(); for(std::set::iterator it=devs.begin(); it!=devs.end(); ++it) { res.insert(Device(this, *it)); } return res; } bool Client::hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException) { std::set names = getDeviceVariableNames(dev); return names.find(name) != names.end(); } std::map > Client::getDeviceVariableValues(const std::string& dev)throw(NutException) { std::map > res; std::set names = getDeviceVariableNames(dev); for(std::set::iterator it=names.begin(); it!=names.end(); ++it) { const std::string& name = *it; res[name] = getDeviceVariableValue(dev, name); } return res; } bool Client::hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException) { std::set names = getDeviceCommandNames(dev); return names.find(name) != names.end(); } /* * * TCP Client implementation * */ TcpClient::TcpClient(): Client(), _host("localhost"), _port(3493), _socket(new internal::Socket) { // Do not connect now } TcpClient::TcpClient(const std::string& host, int port)throw(IOException): Client(), _socket(new internal::Socket) { connect(host, port); } TcpClient::~TcpClient() { delete _socket; } void TcpClient::connect(const std::string& host, int port)throw(IOException) { _host = host; _port = port; connect(); } void TcpClient::connect()throw(nut::IOException) { _socket->connect(_host, _port); } std::string TcpClient::getHost()const { return _host; } int TcpClient::getPort()const { return _port; } bool TcpClient::isConnected()const { return _socket->isConnected(); } void TcpClient::disconnect() { _socket->disconnect(); } void TcpClient::setTimeout(long timeout) { _timeout = timeout; } long TcpClient::getTimeout()const { return _timeout; } void TcpClient::authenticate(const std::string& user, const std::string& passwd) throw(NutException) { detectError(sendQuery("USERNAME " + user)); detectError(sendQuery("PASSWORD " + passwd)); } void TcpClient::logout()throw(NutException) { detectError(sendQuery("LOGOUT")); _socket->disconnect(); } Device TcpClient::getDevice(const std::string& name)throw(NutException) { try { get("UPSDESC", name); } catch(NutException& ex) { if(ex.str()=="UNKNOWN-UPS") return Device(NULL, ""); else throw; } return Device(this, name); } std::set TcpClient::getDeviceNames()throw(NutException) { std::set res; std::vector > devs = list("UPS"); for(std::vector >::iterator it=devs.begin(); it!=devs.end(); ++it) { std::string id = (*it)[0]; if(!id.empty()) res.insert(id); } return res; } std::string TcpClient::getDeviceDescription(const std::string& name)throw(NutException) { return get("UPSDESC", name)[0]; } std::set TcpClient::getDeviceVariableNames(const std::string& dev)throw(NutException) { std::set set; std::vector > res = list("VAR", dev); for(size_t n=0; n TcpClient::getDeviceRWVariableNames(const std::string& dev)throw(NutException) { std::set set; std::vector > res = list("RW", dev); for(size_t n=0; n TcpClient::getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException) { return get("VAR", dev + " " + name); } std::map > TcpClient::getDeviceVariableValues(const std::string& dev)throw(NutException) { std::map > map; std::vector > res = list("VAR", dev); for(size_t n=0; n& vals = res[n]; std::string var = vals[0]; vals.erase(vals.begin()); map[var] = vals; } return map; } void TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException) { std::string query = "SET VAR " + dev + " " + name + " " + escape(value); detectError(sendQuery(query)); } void TcpClient::setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException) { std::string query = "SET VAR " + dev + " " + name; for(size_t n=0; n TcpClient::getDeviceCommandNames(const std::string& dev)throw(NutException) { std::set cmds; std::vector > res = list("CMD", dev); for(size_t n=0; n TcpClient::get (const std::string& subcmd, const std::string& params) throw(NutException) { std::string req = subcmd; if(!params.empty()) { req += " " + params; } std::string res = sendQuery("GET " + req); detectError(res); if(res.substr(0, req.size()) != req) { throw NutException("Invalid response"); } return explode(res, req.size()); } std::vector > TcpClient::list (const std::string& subcmd, const std::string& params) throw(NutException) { std::string req = subcmd; if(!params.empty()) { req += " " + params; } std::string res = sendQuery("LIST " + req); detectError(res); if(res != ("BEGIN LIST " + req)) { throw NutException("Invalid response"); } std::vector > arr; while(true) { res = _socket->read(); detectError(res); if(res == ("END LIST " + req)) { return arr; } if(res.substr(0, req.size()) == req) { arr.push_back(explode(res, req.size())); } else { throw NutException("Invalid response"); } } } std::string TcpClient::sendQuery(const std::string& req)throw(IOException) { _socket->write(req); return _socket->read(); } void TcpClient::detectError(const std::string& req)throw(NutException) { if(req.substr(0,3)=="ERR") { throw NutException(req.substr(4)); } } std::vector TcpClient::explode(const std::string& str, size_t begin) { std::vector res; std::string temp; enum STATE { INIT, SIMPLE_STRING, QUOTED_STRING, SIMPLE_ESCAPE, QUOTED_ESCAPE } state = INIT; for(size_t idx=begin; idxgetDeviceDescription(getName()); } std::vector Device::getVariableValue(const std::string& name) throw(NutException) { return getClient()->getDeviceVariableValue(getName(), name); } std::map > Device::getVariableValues() throw(NutException) { return getClient()->getDeviceVariableValues(getName()); } std::set Device::getVariableNames()throw(NutException) { return getClient()->getDeviceVariableNames(getName()); } std::set Device::getRWVariableNames()throw(NutException) { return getClient()->getDeviceRWVariableNames(getName()); } void Device::setVariable(const std::string& name, const std::string& value)throw(NutException) { getClient()->setDeviceVariable(getName(), name, value); } void Device::setVariable(const std::string& name, const std::vector& values) throw(NutException) { getClient()->setDeviceVariable(getName(), name, values); } Variable Device::getVariable(const std::string& name)throw(NutException) { if(getClient()->hasDeviceVariable(getName(), name)) return Variable(this, name); else return Variable(NULL, ""); } std::set Device::getVariables()throw(NutException) { std::set set; std::set names = getClient()->getDeviceVariableNames(getName()); for(std::set::iterator it=names.begin(); it!=names.end(); ++it) { set.insert(Variable(this, *it)); } return set; } std::set Device::getRWVariables()throw(NutException) { std::set set; std::set names = getClient()->getDeviceRWVariableNames(getName()); for(std::set::iterator it=names.begin(); it!=names.end(); ++it) { set.insert(Variable(this, *it)); } return set; } std::set Device::getCommandNames()throw(NutException) { return getClient()->getDeviceCommandNames(getName()); } std::set Device::getCommands()throw(NutException) { std::set cmds; std::set res = getCommandNames(); for(std::set::iterator it=res.begin(); it!=res.end(); ++it) { cmds.insert(Command(this, *it)); } return cmds; } Command Device::getCommand(const std::string& name)throw(NutException) { if(getClient()->hasDeviceCommand(getName(), name)) return Command(this, name); else return Command(NULL, ""); } void Device::executeCommand(const std::string& name)throw(NutException) { getClient()->executeDeviceCommand(getName(), name); } void Device::login()throw(NutException) { getClient()->deviceLogin(getName()); } void Device::master()throw(NutException) { getClient()->deviceMaster(getName()); } void Device::forcedShutdown()throw(NutException) { } int Device::getNumLogins()throw(NutException) { return getClient()->deviceGetNumLogins(getName()); } /* * * Variable implementation * */ Variable::Variable(Device* dev, const std::string& name): _device(dev), _name(name) { } Variable::Variable(const Variable& var): _device(var._device), _name(var._name) { } Variable::~Variable() { } std::string Variable::getName()const { return _name; } const Device* Variable::getDevice()const { return _device; } Device* Variable::getDevice() { return _device; } bool Variable::isOk()const { return _device!=NULL && !_name.empty(); } Variable::operator bool()const { return isOk(); } bool Variable::operator!()const { return !isOk(); } bool Variable::operator==(const Variable& var)const { return var._device==_device && var._name==_name; } bool Variable::operator<(const Variable& var)const { return getName() Variable::getValue()throw(NutException) { return getDevice()->getClient()->getDeviceVariableValue(getDevice()->getName(), getName()); } std::string Variable::getDescription()throw(NutException) { return getDevice()->getClient()->getDeviceVariableDescription(getDevice()->getName(), getName()); } void Variable::setValue(const std::string& value)throw(NutException) { getDevice()->setVariable(getName(), value); } void Variable::setValues(const std::vector& values)throw(NutException) { getDevice()->setVariable(getName(), values); } /* * * Command implementation * */ Command::Command(Device* dev, const std::string& name): _device(dev), _name(name) { } Command::Command(const Command& cmd): _device(cmd._device), _name(cmd._name) { } Command::~Command() { } std::string Command::getName()const { return _name; } const Device* Command::getDevice()const { return _device; } Device* Command::getDevice() { return _device; } bool Command::isOk()const { return _device!=NULL && !_name.empty(); } Command::operator bool()const { return isOk(); } bool Command::operator!()const { return !isOk(); } bool Command::operator==(const Command& cmd)const { return cmd._device==_device && cmd._name==_name; } bool Command::operator<(const Command& cmd)const { return getName()getClient()->getDeviceCommandDescription(getDevice()->getName(), getName()); } void Command::execute()throw(NutException) { getDevice()->executeCommand(getName()); } } /* namespace nut */ /** * C nutclient API. */ extern "C" { strarr strarr_alloc(unsigned short count) { strarr arr = (strarr)xcalloc(count+1, sizeof(char*)); arr[count] = NULL; return arr; } void strarr_free(strarr arr) { char** pstr = arr; while(*pstr!=NULL) { free(*pstr); ++pstr; } free(arr); } static strarr stringset_to_strarr(const std::set& strset) { strarr arr = strarr_alloc(strset.size()); strarr pstr = arr; for(std::set::const_iterator it=strset.begin(); it!=strset.end(); ++it) { *pstr = xstrdup(it->c_str()); } return arr; } static strarr stringvector_to_strarr(const std::vector& strset) { strarr arr = strarr_alloc(strset.size()); strarr pstr = arr; for(std::vector::const_iterator it=strset.begin(); it!=strset.end(); ++it) { *pstr = xstrdup(it->c_str()); } return arr; } NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, unsigned short port) { nut::TcpClient* client = new nut::TcpClient; try { client->connect(host, port); return (NUTCLIENT_TCP_t)client; } catch(nut::NutException& ex) { // TODO really catch it delete client; return NULL; } } void nutclient_destroy(NUTCLIENT_t client) { if(client) { delete (nut::Client*)client; } } int nutclient_tcp_is_connected(NUTCLIENT_TCP_t client) { if(client) { nut::TcpClient* cl = dynamic_cast((nut::Client*)client); if(cl) { return cl->isConnected() ? 1 : 0; } } return 0; } void nutclient_tcp_disconnect(NUTCLIENT_TCP_t client) { if(client) { nut::TcpClient* cl = dynamic_cast((nut::Client*)client); if(cl) { cl->disconnect(); } } } int nutclient_tcp_reconnect(NUTCLIENT_TCP_t client) { if(client) { nut::TcpClient* cl = dynamic_cast((nut::Client*)client); if(cl) { try { cl->connect(); return 0; } catch(...){} } } return -1; } void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, long timeout) { if(client) { nut::TcpClient* cl = dynamic_cast((nut::Client*)client); if(cl) { cl->setTimeout(timeout); } } } long nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client) { if(client) { nut::TcpClient* cl = dynamic_cast((nut::Client*)client); if(cl) { return cl->getTimeout(); } } return -1; } void nutclient_authenticate(NUTCLIENT_t client, const char* login, const char* passwd) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->authenticate(login, passwd); } catch(...){} } } } void nutclient_logout(NUTCLIENT_t client) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->logout(); } catch(...){} } } } void nutclient_device_login(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->deviceLogin(dev); } catch(...){} } } } int nutclient_get_device_num_logins(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return cl->deviceGetNumLogins(dev); } catch(...){} } } return -1; } void nutclient_device_master(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->deviceMaster(dev); } catch(...){} } } } void nutclient_device_forced_shutdown(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->deviceForcedShutdown(dev); } catch(...){} } } } strarr nutclient_get_devices(NUTCLIENT_t client) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return stringset_to_strarr(cl->getDeviceNames()); } catch(...){} } } return NULL; } int nutclient_has_device(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return cl->hasDevice(dev)?1:0; } catch(...){} } } return 0; } char* nutclient_get_device_description(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return xstrdup(cl->getDeviceDescription(dev).c_str()); } catch(...){} } } return NULL; } strarr nutclient_get_device_variables(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return stringset_to_strarr(cl->getDeviceVariableNames(dev)); } catch(...){} } } return NULL; } strarr nutclient_get_device_rw_variables(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return stringset_to_strarr(cl->getDeviceRWVariableNames(dev)); } catch(...){} } } return NULL; } int nutclient_has_device_variable(NUTCLIENT_t client, const char* dev, const char* var) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return cl->hasDeviceVariable(dev, var)?1:0; } catch(...){} } } return 0; } char* nutclient_get_device_variable_description(NUTCLIENT_t client, const char* dev, const char* var) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return xstrdup(cl->getDeviceVariableDescription(dev, var).c_str()); } catch(...){} } } return NULL; } strarr nutclient_get_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return stringvector_to_strarr(cl->getDeviceVariableValue(dev, var)); } catch(...){} } } return NULL; } void nutclient_set_device_variable_value(NUTCLIENT_t client, const char* dev, const char* var, const char* value) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->setDeviceVariable(dev, var, value); } catch(...){} } } } void nutclient_set_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var, const strarr values) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { std::vector vals; strarr pstr = (strarr)values; while(*pstr) { vals.push_back(std::string(*pstr)); ++pstr; } cl->setDeviceVariable(dev, var, vals); } catch(...){} } } } strarr nutclient_get_device_commands(NUTCLIENT_t client, const char* dev) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return stringset_to_strarr(cl->getDeviceCommandNames(dev)); } catch(...){} } } return NULL; } int nutclient_has_device_command(NUTCLIENT_t client, const char* dev, const char* cmd) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return cl->hasDeviceCommand(dev, cmd)?1:0; } catch(...){} } } return 0; } char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* dev, const char* cmd) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { return xstrdup(cl->getDeviceCommandDescription(dev, cmd).c_str()); } catch(...){} } } return NULL; } void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd) { if(client) { nut::Client* cl = (nut::Client*)client; if(cl) { try { cl->executeDeviceCommand(dev, cmd); } catch(...){} } } } } /* extern "C" */ nut-2.7.2/clients/upslog.h0000644000175000017500000000150412277355125012405 00000000000000/* upslog.h - table of functions for handling various logging functions */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* function list */ typedef struct flist_s { void (*fptr)(const char *arg); const char *arg; struct flist_s *next; } flist_t; static void do_host(const char *arg); static void do_upshost(const char *arg); static void do_pid(const char *arg); static void do_time(const char *arg); static void do_var(const char *arg); static void do_etime(const char *arg); struct { const char *name; void (*func)(const char *arg); } logcmds[] = { { "HOST", do_host }, { "UPSHOST", do_upshost }, { "PID", do_pid }, { "TIME", do_time }, { "VAR", do_var }, { "ETIME", do_etime }, { NULL, (void(*)())(NULL) } }; #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/upsstats.c0000644000175000017500000005076212277355125012767 00000000000000/* upsstats - cgi program to generate the main ups info page Copyright (C) 1998 Russell Kroll Copyright (C) 2005 Arnaud Quette This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "upsclient.h" #include "status.h" #include "cgilib.h" #include "parseconf.h" #include "timehead.h" #include "upsstats.h" #include "upsimagearg.h" #define MAX_CGI_STRLEN 128 #define MAX_PARSE_ARGS 16 static char *monhost = NULL; static int use_celsius = 1, refreshdelay = -1, treemode = 0; /* from cgilib's checkhost() */ static char *monhostdesc = NULL; static int port; static char *upsname, *hostname; static char *upsimgpath="upsimage.cgi", *upsstatpath="upsstats.cgi"; static UPSCONN_t ups; static FILE *tf; static long forofs = 0; static ulist_t *ulhead = NULL, *currups = NULL; static int skip_clause = 0, skip_block = 0; void parsearg(char *var, char *value) { /* avoid bogus junk from evil people */ if ((strlen(var) > MAX_CGI_STRLEN) || (strlen(value) > MAX_CGI_STRLEN)) return; if (!strcmp(var, "host")) { free(monhost); monhost = xstrdup(value); return; } if (!strcmp(var, "refresh")) refreshdelay = (int) strtol(value, (char **) NULL, 10); if (!strcmp(var, "treemode")) { /* FIXME: Validate that treemode is allowed */ treemode = 1; } } static void report_error(void) { if (upscli_upserror(&ups) == UPSCLI_ERR_VARNOTSUPP) printf("Not supported\n"); else printf("[error: %s]\n", upscli_strerror(&ups)); } /* make sure we're actually connected to upsd */ static int check_ups_fd(int do_report) { if (upscli_fd(&ups) == -1) { if (do_report) report_error(); return 0; } /* also check for insanity in currups */ if (!currups) { if (do_report) printf("No UPS specified for monitoring\n"); return 0; } /* must be OK */ return 1; } static int get_var(const char *var, char *buf, size_t buflen, int verbose) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; if (!check_ups_fd(1)) return 0; if (!upsname) { if (verbose) printf("[No UPS name specified]\n"); return 0; } query[0] = "VAR"; query[1] = upsname; query[2] = var; numq = 3; ret = upscli_get(&ups, numq, query, &numa, &answer); if (ret < 0) { if (verbose) report_error(); return 0; } if (numa < numq) { if (verbose) printf("[Invalid response]\n"); return 0; } snprintf(buf, buflen, "%s", answer[3]); return 1; } static void parse_var(const char *var) { char answer[SMALLBUF]; if (!get_var(var, answer, sizeof(answer), 1)) return; printf("%s", answer); } static void do_status(void) { int i; char status[SMALLBUF], *ptr, *last = NULL; if (!get_var("ups.status", status, sizeof(status), 1)) { return; } for (ptr = strtok_r(status, " \n", &last); ptr != NULL; ptr = strtok_r(NULL, " \n", &last)) { /* expand from table in status.h */ for (i = 0; stattab[i].name != NULL; i++) { if (!strcasecmp(ptr, stattab[i].name)) { printf("%s
", stattab[i].desc); } } } } static void do_runtime(void) { int total, hours, minutes, seconds; char runtime[SMALLBUF]; if (!get_var("battery.runtime", runtime, sizeof(runtime), 1)) return; total = (int) strtol(runtime, (char **) NULL, 10); hours = total / 3600; minutes = (total - (hours * 3600)) / 60; seconds = total % 60; printf("%02d:%02d:%02d", hours, minutes, seconds); } static int do_date(const char *buf) { char datebuf[SMALLBUF]; time_t tod; time(&tod); if (strftime(datebuf, sizeof(datebuf), buf, localtime(&tod))) { printf("%s", datebuf); return 1; } return 0; } static int get_img_val(const char *var, const char *desc, const char *imgargs) { char answer[SMALLBUF]; if (!get_var(var, answer, sizeof(answer), 1)) return 1; printf("sys, var); if ((imgargs) && (strlen(imgargs) > 0)) printf("&%s", imgargs); printf("\" ALT=\"%s: %s\">", desc, answer); return 1; } /* see if is valid - table from upsimagearg.h */ static void check_imgarg(char *arg, char *out, size_t outlen) { int i; char *ep; ep = strchr(arg, '='); if (!ep) return; *ep++= '\0'; /* if it's allowed, append it so it can become part of the URL */ for (i = 0; imgarg[i].name != NULL; i++) { if (!strcmp(imgarg[i].name, arg)) { if (strlen(out) == 0) snprintf(out, outlen, "%s=%s", arg, ep); else snprintfcat(out, outlen, "&%s=%s", arg, ep); return; } } } /* split out the var=val commands from the IMG line */ static void split_imgarg(char *in, char *out, size_t outlen) { char *ptr, *sp; if (strlen(in) < 3) return; ptr = in; sp = strchr(ptr, ' '); /* split by spaces, then check each one (can't use parseconf...) */ while (sp) { *sp++ = '\0'; check_imgarg(ptr, out, outlen); ptr = sp; sp = strchr(ptr, ' '); } check_imgarg(ptr, out, outlen); } /* IMG [==] ... */ static int do_img(char *buf) { char *type, *ptr, imgargs[SMALLBUF]; memset(imgargs, '\0', sizeof(imgargs)); type = buf; ptr = strchr(buf, ' '); if (ptr) { *ptr++ = '\0'; split_imgarg(ptr, imgargs, sizeof(imgargs)); } /* only allow known types through */ if (!strcmp(type, "input.voltage") || !strcmp(type, "input.L1-N.voltage") || !strcmp(type, "input.L2-N.voltage") || !strcmp(type, "input.L3-N.voltage") || !strcmp(type, "input.L1-L2.voltage") || !strcmp(type, "input.L2-L3.voltage") || !strcmp(type, "input.L3-L1.voltage")) { return get_img_val(type, "Input voltage", imgargs); } if (!strcmp(type, "battery.voltage")) return get_img_val(type, "Battery voltage", imgargs); if (!strcmp(type, "battery.charge")) return get_img_val(type, "Battery charge", imgargs); if (!strcmp(type, "output.voltage") || !strcmp(type, "output.L1-N.voltage") || !strcmp(type, "output.L2-N.voltage") || !strcmp(type, "output.L3-N.voltage") || !strcmp(type, "output.L1-L2.voltage") || !strcmp(type, "output.L2-L3.voltage") || !strcmp(type, "output.L3-L1.voltage")) { return get_img_val(type, "Output voltage", imgargs); } if (!strcmp(type, "ups.load") || !strcmp(type, "output.L1.power.percent") || !strcmp(type, "output.L2.power.percent") || !strcmp(type, "output.L3.power.percent") || !strcmp(type, "output.L1.realpower.percent") || !strcmp(type, "output.L2.realpower.percent") || !strcmp(type, "output.L3.realpower.percent")) { return get_img_val(type, "UPS load", imgargs); } if (!strcmp(type, "input.frequency")) return get_img_val(type, "Input frequency", imgargs); if (!strcmp(type, "output.frequency")) return get_img_val(type, "Output frequency", imgargs); if (!strcmp(type, "ups.temperature")) return get_img_val(type, "UPS temperature", imgargs); if (!strcmp(type, "ambient.temperature")) return get_img_val(type, "Ambient temperature", imgargs); if (!strcmp(type, "ambient.humidity")) return get_img_val(type, "Ambient humidity", imgargs); return 0; } static void ups_connect(void) { static ulist_t *lastups = NULL; char *newups, *newhost; int newport; /* try to minimize reconnects */ if (lastups) { /* don't reconnect if these are both the same UPS */ if (!strcmp(lastups->sys, currups->sys)) { lastups = currups; return; } /* see if it's just on the same host */ newups = newhost = NULL; if (upscli_splitname(currups->sys, &newups, &newhost, &newport) != 0) { printf("Unusable UPS definition [%s]\n", currups->sys); fprintf(stderr, "Unusable UPS definition [%s]\n", currups->sys); exit(EXIT_FAILURE); } if ((!strcmp(newhost, hostname)) && (port == newport)) { free(upsname); upsname = newups; free(newhost); lastups = currups; return; } /* not the same upsd, so disconnect */ free(newups); free(newhost); } upscli_disconnect(&ups); free(upsname); free(hostname); if (upscli_splitname(currups->sys, &upsname, &hostname, &port) != 0) { printf("Unusable UPS definition [%s]\n", currups->sys); fprintf(stderr, "Unusable UPS definition [%s]\n", currups->sys); exit(EXIT_FAILURE); } if (upscli_connect(&ups, hostname, port, 0) < 0) fprintf(stderr, "UPS [%s]: can't connect to server: %s\n", currups->sys, upscli_strerror(&ups)); lastups = currups; } static void do_hostlink(void) { if (!currups) { return; } printf("sys); if (refreshdelay > 0) { printf("&refresh=%d", refreshdelay); } printf("\">%s", currups->desc); } static void do_treelink(void) { if (!currups) { return; } printf("All data", upsstatpath, currups->sys); } /* see if the UPS supports this variable - skip to the next ENDIF if not */ /* if val is not null, value returned by var must be equal to val to match */ static void do_ifsupp(const char *var, const char *val) { char dummy[SMALLBUF]; /* if not connected, act like it's not supported and skip the rest */ if (!check_ups_fd(0)) { skip_clause = 1; return; } if (!get_var(var, dummy, sizeof(dummy), 0)) { skip_clause = 1; return; } if(!val) { return; } if(strcmp(dummy, val)) { skip_clause = 1; return; } } static int breakargs(char *s, char **aargs) { char *p; int i=0; aargs[i]=NULL; for(p=s; *p && i<(MAX_PARSE_ARGS-1); p++) { if(aargs[i] == NULL) { aargs[i] = p; aargs[i+1] = NULL; } if(*p==' ') { *p='\0'; i++; } } /* Check how many valid args we got */ for(i=0; aargs[i]; i++); return i; } static void do_ifeq(const char *s) { char var[SMALLBUF]; char *aa[MAX_PARSE_ARGS]; int nargs; strcpy(var, s); nargs = breakargs(var, aa); if(nargs != 2) { printf("upsstats: IFEQ: Argument error!\n"); return; } do_ifsupp(aa[0], aa[1]); } /* IFBETWEEN var1 var2 var3. Skip if var3 not between var1 * and var2 */ static void do_ifbetween(const char *s) { char var[SMALLBUF]; char *aa[MAX_PARSE_ARGS]; char tmp[SMALLBUF]; int nargs; long v1, v2, v3; char *isvalid=NULL; strcpy(var, s); nargs = breakargs(var, aa); if(nargs != 3) { printf("upsstats: IFBETWEEN: Argument error!\n"); return; } if (!check_ups_fd(0)) { return; } if (!get_var(aa[0], tmp, sizeof(tmp), 0)) { return; } v1 = strtol(tmp, &isvalid, 10); if(tmp == isvalid) { return; } if (!get_var(aa[1], tmp, sizeof(tmp), 0)) { return; } v2 = strtol(tmp, &isvalid, 10); if(tmp == isvalid) { return; } if (!get_var(aa[2], tmp, sizeof(tmp), 0)) { return; } v3 = strtol(tmp, &isvalid, 10); if(tmp == isvalid) { return; } if(v1 > v3 || v2 < v3) { skip_clause = 1; return; } } static void do_upsstatpath(const char *s) { if(strlen(s)) { upsstatpath = strdup(s); } } static void do_upsimgpath(const char *s) { if(strlen(s)) { upsimgpath = strdup(s); } } static void do_temp(const char *var) { char tempc[SMALLBUF]; float tempf; if (!get_var(var, tempc, sizeof(tempc), 1)) return; if (use_celsius) { printf("%s", tempc); return; } tempf = (strtod(tempc, (char **) NULL) * 1.8) + 32; printf("%.1f", tempf); } static void do_degrees(void) { printf("°"); if (use_celsius) printf("C"); else printf("F"); } /* plug in the right color string (like #FF0000) for the UPS status */ static void do_statuscolor(void) { int severity, i; char stat[SMALLBUF], *sp, *ptr; if (!check_ups_fd(0)) { /* can't print the warning here - give a red error condition */ printf("#FF0000"); return; } if (!get_var("ups.status", stat, sizeof(stat), 0)) { /* status not available - give yellow as a warning */ printf("#FFFF00"); return; } severity = 0; sp = stat; while (sp) { ptr = strchr(sp, ' '); if (ptr) *ptr++ = '\0'; /* expand from table in status.h */ for (i = 0; stattab[i].name != NULL; i++) if (!strcmp(stattab[i].name, sp)) if (stattab[i].severity > severity) severity = stattab[i].severity; sp = ptr; } switch(severity) { case 0: printf("#00FF00"); break; /* green : OK */ case 1: printf("#FFFF00"); break; /* yellow : warning */ default: printf("#FF0000"); break; /* red : error */ } } static int do_command(char *cmd) { /* ending an if block? */ if (!strcmp(cmd, "ENDIF")) { skip_clause = 0; skip_block = 0; return 1; } /* Skipping a block means skip until ENDIF, so... */ if (skip_block) { return 1; } /* Toggle state when we run across ELSE */ if (!strcmp(cmd, "ELSE")) { if (skip_clause) { skip_clause = 0; } else { skip_block = 1; } return 1; } /* don't do any commands if skipping a section */ if (skip_clause == 1) { return 1; } if (!strncmp(cmd, "VAR ", 4)) { parse_var(&cmd[4]); return 1; } if (!strcmp(cmd, "HOST")) { printf("%s", currups->sys); return 1; } if (!strcmp(cmd, "HOSTDESC")) { printf("%s", currups->desc); return 1; } if (!strcmp(cmd, "RUNTIME")) { do_runtime(); return 1; } if (!strcmp(cmd, "STATUS")) { do_status(); return 1; } if (!strcmp(cmd, "STATUSCOLOR")) { do_statuscolor(); return 1; } if (!strcmp(cmd, "TEMPF")) { use_celsius = 0; return 1; } if (!strcmp(cmd, "TEMPC")) { use_celsius = 1; return 1; } if (!strncmp(cmd, "DATE ", 5)) { return do_date(&cmd[5]); } if (!strncmp(cmd, "IMG ", 4)) { return do_img(&cmd[4]); } if (!strcmp(cmd, "VERSION")) { printf("%s", UPS_VERSION); return 1; } if (!strcmp(cmd, "REFRESH")) { if (refreshdelay > 0) { printf("", refreshdelay); } return 1; } if (!strcmp(cmd, "FOREACHUPS")) { forofs = ftell(tf); currups = ulhead; ups_connect(); return 1; } if (!strcmp(cmd, "ENDFOR")) { /* if not in a for, ignore this */ if (forofs == 0) { return 1; } currups = currups->next; if (currups) { fseek(tf, forofs, SEEK_SET); ups_connect(); } return 1; } if (!strcmp(cmd, "HOSTLINK")) { do_hostlink(); return 1; } if (!strcmp(cmd, "TREELINK")) { do_treelink(); return 1; } if (!strncmp(cmd, "IFSUPP ", 7)) { do_ifsupp(&cmd[7], NULL); return 1; } if (!strcmp(cmd, "UPSTEMP")) { do_temp("ups.temperature"); return 1; } if (!strcmp(cmd, "BATTTEMP")) { do_temp("battery.temperature"); return 1; } if (!strcmp(cmd, "AMBTEMP")) { do_temp("ambient.temperature"); return 1; } if (!strcmp(cmd, "DEGREES")) { do_degrees(); return 1; } if (!strncmp(cmd, "IFEQ ", 5)) { do_ifeq(&cmd[5]); return 1; } if (!strncmp(cmd, "IFBETWEEN ", 10)) { do_ifbetween(&cmd[10]); return 1; } if (!strncmp(cmd, "UPSSTATSPATH ", 13)) { do_upsstatpath(&cmd[13]); return 1; } if (!strncmp(cmd, "UPSIMAGEPATH ", 13)) { do_upsimgpath(&cmd[13]); return 1; } return 0; } static void parse_line(const char *buf) { char cmd[SMALLBUF]; int i, len, do_cmd = 0; for (i = 0; buf[i]; i += len) { len = strcspn(&buf[i], "@"); if (len == 0) { if (do_cmd) { do_command(cmd); do_cmd = 0; } else { cmd[0] = '\0'; do_cmd = 1; } i++; /* skip over the '@' character */ continue; } if (do_cmd) { snprintf(cmd, sizeof(cmd), "%.*s", len, &buf[i]); continue; } if (skip_clause || skip_block) { /* ignore this */ continue; } /* pass it trough */ printf("%.*s", len, &buf[i]); } } static void display_template(const char *tfn) { char fn[SMALLBUF], buf[LARGEBUF]; snprintf(fn, sizeof(fn), "%s/%s", confpath(), tfn); tf = fopen(fn, "r"); if (!tf) { fprintf(stderr, "upsstats: Can't open %s: %s\n", fn, strerror(errno)); printf("Error: can't open template file (%s)\n", tfn); exit(EXIT_FAILURE); } while (fgets(buf, sizeof(buf), tf)) { parse_line(buf); } fclose(tf); } static void display_tree(int verbose) { unsigned int numq, numa; const char *query[4]; char **answer; if (!upsname) { if (verbose) printf("[No UPS name specified]\n"); return; } query[0] = "VAR"; query[1] = upsname; numq = 2; if (upscli_list_start(&ups, numq, query) < 0) { if (verbose) report_error(); return; } printf("\n"); printf("\n"); printf("upsstat: data tree of %s\n", currups->desc); printf("\n"); printf("\n"); printf("
\n"); printf("\n"); /* include the description from checkhost() if present */ printf("\n"); printf("\n"); while (upscli_list_next(&ups, numq, query, &numa, &answer) == 1) { /* VAR */ if (numa < 4) { if (verbose) printf("[Invalid response]\n"); return; } printf("\n"); printf("\n", answer[2]); printf("\n"); printf("\n", answer[3]); printf("\n"); } printf("
\n"); printf("%s\n", currups->desc); printf("
%s:%s
\n"); printf("
\n"); /* FIXME (AQ): add a save button (?), and a checkbt for showing var.desc */ printf("\n"); } static void add_ups(char *sys, char *desc) { ulist_t *tmp, *last; tmp = last = ulhead; while (tmp) { last = tmp; tmp = tmp->next; } tmp = xmalloc(sizeof(ulist_t)); tmp->sys = xstrdup(sys); tmp->desc = xstrdup(desc); tmp->next = NULL; if (last) last->next = tmp; else ulhead = tmp; } /* called for fatal errors in parseconf like malloc failures */ static void upsstats_hosts_err(const char *errmsg) { upslogx(LOG_ERR, "Fatal error in parseconf(hosts.conf): %s", errmsg); } static void load_hosts_conf(void) { char fn[SMALLBUF]; PCONF_CTX_t ctx; snprintf(fn, sizeof(fn), "%s/hosts.conf", CONFPATH); pconf_init(&ctx, upsstats_hosts_err); if (!pconf_file_begin(&ctx, fn)) { pconf_finish(&ctx); printf("\n"); printf("\n"); printf("Error: can't open hosts.conf\n"); printf("\n"); printf("Error: can't open hosts.conf\n"); printf("\n"); /* leave something for the admin */ fprintf(stderr, "upsstats: %s\n", ctx.errmsg); exit(EXIT_FAILURE); } while (pconf_file_next(&ctx)) { if (pconf_parse_error(&ctx)) { upslogx(LOG_ERR, "Parse error: %s:%d: %s", fn, ctx.linenum, ctx.errmsg); continue; } if (ctx.numargs < 3) continue; /* MONITOR */ if (!strcmp(ctx.arglist[0], "MONITOR")) add_ups(ctx.arglist[1], ctx.arglist[2]); } pconf_finish(&ctx); if (!ulhead) { printf("\n"); printf("\n"); printf("Error: no hosts to monitor\n"); printf("\n"); printf("Error: no hosts to monitor (check hosts.conf)\n"); printf("\n"); /* leave something for the admin */ fprintf(stderr, "upsstats: no hosts to monitor\n"); exit(EXIT_FAILURE); } } static void display_single(void) { if (!checkhost(monhost, &monhostdesc)) { printf("Access to that host [%s] is not authorized.\n", monhost); exit(EXIT_FAILURE); } add_ups(monhost, monhostdesc); currups = ulhead; ups_connect(); /* switch between data tree view and standard single view */ if (treemode) display_tree(1); else display_template("upsstats-single.html"); upscli_disconnect(&ups); } int main(int argc, char **argv) { extractcgiargs(); printf("Content-type: text/html\n"); printf("Pragma: no-cache\n"); printf("\n"); /* if a host is specified, use upsstats-single.html instead */ if (monhost) { display_single(); exit(EXIT_SUCCESS); } /* default: multimon replacement mode */ load_hosts_conf(); currups = ulhead; display_template("upsstats.html"); upscli_disconnect(&ups); return 0; } nut-2.7.2/clients/nutclient.h0000644000175000017500000006546112303134465013105 00000000000000/* nutclient.h - definitions for nutclient C/C++ library Copyright (C) 2012 Emilien Kia This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef NUTCLIENT_HPP_SEEN #define NUTCLIENT_HPP_SEEN /* Begin of C++ nutclient library declaration */ #ifdef __cplusplus #include #include #include #include #include namespace nut { namespace internal { class Socket; } /* namespace internal */ class Client; class TcpClient; class Device; class Variable; class Command; /** * Basic nut exception. */ class NutException : public std::exception { public: NutException(const std::string& msg):_msg(msg){} virtual ~NutException() throw() {} virtual const char * what() const throw() {return this->_msg.c_str();} virtual std::string str() const throw() {return this->_msg;} private: std::string _msg; }; /** * System error. */ class SystemException : public NutException { public: SystemException(); virtual ~SystemException() throw() {} private: static std::string err(); }; /** * IO oriented nut exception. */ class IOException : public NutException { public: IOException(const std::string& msg):NutException(msg){} virtual ~IOException() throw() {} }; /** * IO oriented nut exception specialized for unknown host */ class UnknownHostException : public IOException { public: UnknownHostException():IOException("Unknown host"){} virtual ~UnknownHostException() throw() {} }; /** * IO oriented nut exception when client is not connected */ class NotConnectedException : public IOException { public: NotConnectedException():IOException("Not connected"){} virtual ~NotConnectedException() throw() {} }; /** * IO oriented nut exception when there is no response. */ class TimeoutException : public IOException { public: TimeoutException():IOException("Timeout"){} virtual ~TimeoutException() throw() {} }; /** * A nut client is the starting point to dialog to NUTD. * It can connect to an NUTD then retrieve its device list. * Use a specific client class to connect to a NUTD. */ class Client { friend class Device; friend class Variable; friend class Command; public: ~Client(); /** * Intend to authenticate to a NUTD server. * Set the username and password associated to the connection. * \param user User name. * \param passwd Password. * \todo Is his method is global to all connection protocol or is it specific to TCP ? * \note Actually, authentication fails only if already set, not if bad values are sent. */ virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException)=0; /** * Disconnect from the NUTD server. * \todo Is his method is global to all connection protocol or is it specific to TCP ? */ virtual void logout()throw(NutException)=0; /** * Device manipulations. * \see nut::Device * \{ */ /** * Retrieve a device from its name. * If the device does not exist, a bad (not ok) device is returned. * \param name Name of the device. * \return The device. */ virtual Device getDevice(const std::string& name)throw(NutException); /** * Retrieve the list of all devices supported by UPSD server. * \return The set of supported devices. */ virtual std::set getDevices()throw(NutException); /** * Test if a device is supported by the NUTD server. * \param dev Device name. * \return true if supported, false otherwise. */ virtual bool hasDevice(const std::string& dev)throw(NutException); /** * Retrieve names of devices supported by NUTD server. * \return The set of names of supported devices. */ virtual std::set getDeviceNames()throw(NutException)=0; /** * Retrieve the description of a device. * \param name Device name. * \return Device description. */ virtual std::string getDeviceDescription(const std::string& name)throw(NutException)=0; /** \} */ /** * Variable manipulations. * \see nut::Variable * \{ */ /** * Retrieve names of all variables supported by a device. * \param dev Device name * \return Variable names */ virtual std::set getDeviceVariableNames(const std::string& dev)throw(NutException)=0; /** * Retrieve names of read/write variables supported by a device. * \param dev Device name * \return RW variable names */ virtual std::set getDeviceRWVariableNames(const std::string& dev)throw(NutException)=0; /** * Test if a variable is supported by a device. * \param dev Device name * \param name Variable name * \return true if the variable is supported. */ virtual bool hasDeviceVariable(const std::string& dev, const std::string& name)throw(NutException); /** * Retrieve the description of a variable. * \param dev Device name * \param name Variable name * \return Variable description if provided. */ virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException)=0; /** * Retrieve values of a variable. * \param dev Device name * \param name Variable name * \return Variable values (usually one) if available. */ virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException)=0; /** * Retrieve values of all variables of a device. * \param dev Device name * \return Variable values indexed by variable names. */ virtual std::map > getDeviceVariableValues(const std::string& dev)throw(NutException); /** * Intend to set the value of a variable. * \param dev Device name * \param name Variable name * \param value Variable value */ virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException)=0; /** * Intend to set the value of a variable. * \param dev Device name * \param name Variable name * \param value Variable value */ virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException)=0; /** \} */ /** * Instant command manipulations. * \see nut::Command * \{ */ /** * Retrieve names of all commands supported by a device. * \param dev Device name * \return Command names */ virtual std::set getDeviceCommandNames(const std::string& dev)throw(NutException)=0; /** * Test if a command is supported by a device. * \param dev Device name * \param name Command name * \return true if the command is supported. */ virtual bool hasDeviceCommand(const std::string& dev, const std::string& name)throw(NutException); /** * Retrieve the description of a command. * \param dev Device name * \param name Command name * \return Command description if provided. */ virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException)=0; /** * Intend to execute a command. * \param dev Device name * \param name Command name */ virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException)=0; /** \} */ /** * Device specific commands. * \{ */ /** * Log the current user (if authenticated) for a device. * \param dev Device name. */ virtual void deviceLogin(const std::string& dev)throw(NutException)=0; /** * Retrieve the number of user longged in the specified device. * \param dev Device name. * \return Number of logged-in users. */ virtual int deviceGetNumLogins(const std::string& dev)throw(NutException)=0; virtual void deviceMaster(const std::string& dev)throw(NutException)=0; virtual void deviceForcedShutdown(const std::string& dev)throw(NutException)=0; protected: Client(); }; /** * TCP NUTD client. * It connect to NUTD with a TCP socket. */ class TcpClient : public Client { public: /** * Construct a nut TcpClient object. * You must call one of TcpClient::connect() after. */ TcpClient(); /** * Construct a nut TcpClient object then connect it to the specified server. * \param host Server host name. * \param port Server port. */ TcpClient(const std::string& host, int port = 3493)throw(nut::IOException); ~TcpClient(); /** * Connect it to the specified server. * \param host Server host name. * \param port Server port. */ void connect(const std::string& host, int port = 3493)throw(nut::IOException); /** * Connect to the server. * Host name and ports must have already set (usefull for reconnection). */ void connect()throw(nut::IOException); /** * Test if the connection is active. * \return tru if the connection is active. */ bool isConnected()const; /** * Force the deconnection. */ void disconnect(); /** * Set the timeout in seconds. * \param timeout Timeout n seconds, negative to block operations. */ void setTimeout(long timeout); /** * Retrieve the timeout. * \returns Current timeout in seconds. */ long getTimeout()const; /** * Retriueve the host name of the server the client is connected to. * \return Server host name */ std::string getHost()const; /** * Retriueve the port of host of the server the client is connected to. * \return Server port */ int getPort()const; virtual void authenticate(const std::string& user, const std::string& passwd)throw(NutException); virtual void logout()throw(NutException); virtual Device getDevice(const std::string& name)throw(NutException); virtual std::set getDeviceNames()throw(NutException); virtual std::string getDeviceDescription(const std::string& name)throw(NutException); virtual std::set getDeviceVariableNames(const std::string& dev)throw(NutException); virtual std::set getDeviceRWVariableNames(const std::string& dev)throw(NutException); virtual std::string getDeviceVariableDescription(const std::string& dev, const std::string& name)throw(NutException); virtual std::vector getDeviceVariableValue(const std::string& dev, const std::string& name)throw(NutException); virtual std::map > getDeviceVariableValues(const std::string& dev)throw(NutException); virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::string& value)throw(NutException); virtual void setDeviceVariable(const std::string& dev, const std::string& name, const std::vector& values)throw(NutException); virtual std::set getDeviceCommandNames(const std::string& dev)throw(NutException); virtual std::string getDeviceCommandDescription(const std::string& dev, const std::string& name)throw(NutException); virtual void executeDeviceCommand(const std::string& dev, const std::string& name)throw(NutException); virtual void deviceLogin(const std::string& dev)throw(NutException); virtual void deviceMaster(const std::string& dev)throw(NutException); virtual void deviceForcedShutdown(const std::string& dev)throw(NutException); virtual int deviceGetNumLogins(const std::string& dev)throw(NutException); protected: std::string sendQuery(const std::string& req)throw(nut::IOException); static void detectError(const std::string& req)throw(nut::NutException); std::vector get(const std::string& subcmd, const std::string& params = "") throw(nut::NutException); std::vector > list(const std::string& subcmd, const std::string& params = "") throw(nut::NutException); static std::vector explode(const std::string& str, size_t begin=0); static std::string escape(const std::string& str); private: std::string _host; int _port; long _timeout; internal::Socket* _socket; }; /** * Device attached to a client. * Device is a lightweight class which can be copied easily. */ class Device { friend class Client; friend class TcpClient; public: ~Device(); Device(const Device& dev); /** * Retrieve the name of the device. * The name is the unique id under which NUTD known the device. */ std::string getName()const; /** * Retrieve the client to which the device is attached. */ const Client* getClient()const; /** * Retrieve the client to which the device is attached. */ Client* getClient(); /** * Test if the device is valid (has a name and is attached to a client). */ bool isOk()const; /** * Test if the device is valid (has a name and is attached to a client). * @see Device::isOk() */ operator bool()const; /** * Test if the device is not valid (has no name or is not attached to any client). * @see Device::isOk() */ bool operator!()const; /** * Test if the two devices are sames (same name ad same client attached to). */ bool operator==(const Device& dev)const; /** * Comparison operator. */ bool operator<(const Device& dev)const; /** * Retrieve the description of the devce if specified. */ std::string getDescription()throw(NutException); /** * Intend to retrieve the value of a variable of the device. * \param name Name of the variable to get. * \return Value of the variable, if available. */ std::vector getVariableValue(const std::string& name)throw(NutException); /** * Intend to retrieve values of all variables of the devices. * \return Map of all variables values indexed by their names. */ std::map > getVariableValues()throw(NutException); /** * Retrieve all variables names supported by the device. * \return Set of available variable names. */ std::set getVariableNames()throw(NutException); /** * Retrieve all Read/Write variables names supported by the device. * \return Set of available Read/Write variable names. */ std::set getRWVariableNames()throw(NutException); /** * Intend to set the value of a variable of the device. * \param name Variable name. * \param value New variable value. */ void setVariable(const std::string& name, const std::string& value)throw(NutException); /** * Intend to set values of a variable of the device. * \param name Variable name. * \param value New variable values. */ void setVariable(const std::string& name, const std::vector& values)throw(NutException); /** * Retrieve a Variable object representing the specified variable. * \param name Variable name. * \return Variable object. */ Variable getVariable(const std::string& name)throw(NutException); /** * Retrieve Variable objects representing all variables available for the device. * \return Set of Variable objects. */ std::set getVariables()throw(NutException); /** * Retrieve Variable objects representing all Read/Write variables available for the device. * \return Set of Variable objects. */ std::set getRWVariables()throw(NutException); /** * Retrieve names of all commands supported by the device. * \return Set of available command names. */ std::set getCommandNames()throw(NutException); /** * Retrieve objects for all commands supported by the device. * \return Set of available Command objects. */ std::set getCommands()throw(NutException); /** * Retrieve an object representing a command of the device. * \param name Command name. * \return Command object. */ Command getCommand(const std::string& name)throw(NutException); /** * Intend to execute a command on the device. * \param name Command name. */ void executeCommand(const std::string& name)throw(NutException); /** * Login current client's user for the device. */ void login()throw(NutException); void master()throw(NutException); void forcedShutdown()throw(NutException); /** * Retrieve the number of logged user for the device. * \return Number of users. */ int getNumLogins()throw(NutException); protected: Device(Client* client, const std::string& name); private: Client* _client; std::string _name; }; /** * Variable attached to a device. * Variable is a lightweight class which can be copied easily. */ class Variable { friend class Device; friend class TcpClient; public: ~Variable(); Variable(const Variable& var); /** * Retrieve variable name. */ std::string getName()const; /** * Retrieve the device to which the variable is attached to. */ const Device* getDevice()const; /** * Retrieve the device to which the variable is attached to. */ Device* getDevice(); /** * Test if the variable is valid (has a name and is attached to a device). */ bool isOk()const; /** * Test if the variable is valid (has a name and is attached to a device). * @see Variable::isOk() */ operator bool()const; /** * Test if the variable is not valid (has no name or is not attached to any device). * @see Variable::isOk() */ bool operator!()const; /** * Test if the two variables are sames (same name ad same device attached to). */ bool operator==(const Variable& var)const; /** * Less-than operator (based on variable name) to allow variable sorting. */ bool operator<(const Variable& var)const; /** * Intend to retrieve variable value. * \return Value of the variable. */ std::vector getValue()throw(NutException); /** * Intend to retireve variable description. * \return Variable description if provided. */ std::string getDescription()throw(NutException); /** * Intend to set a value to the variable. * \param value New variable value. */ void setValue(const std::string& value)throw(NutException); /** * Intend to set (multiple) values to the variable. * \param value New variable values. */ void setValues(const std::vector& values)throw(NutException); protected: Variable(Device* dev, const std::string& name); private: Device* _device; std::string _name; }; /** * Command attached to a device. * Command is a lightweight class which can be copied easily. */ class Command { friend class Device; friend class TcpClient; public: ~Command(); Command(const Command& cmd); /** * Retrieve command name. */ std::string getName()const; /** * Retrieve the device to which the command is attached to. */ const Device* getDevice()const; /** * Retrieve the device to which the command is attached to. */ Device* getDevice(); /** * Test if the command is valid (has a name and is attached to a device). */ bool isOk()const; /** * Test if the command is valid (has a name and is attached to a device). * @see Command::isOk() */ operator bool()const; /** * Test if the command is not valid (has no name or is not attached to any device). * @see Command::isOk() */ bool operator!()const; /** * Test if the two commands are sames (same name ad same device attached to). */ bool operator==(const Command& var)const; /** * Less-than operator (based on command name) to allow comand sorting. */ bool operator<(const Command& var)const; /** * Intend to retireve command description. * \return Command description if provided. */ std::string getDescription()throw(NutException); /** * Intend to retrieve command description. * \return Command description if provided. */ void execute()throw(NutException); protected: Command(Device* dev, const std::string& name); private: Device* _device; std::string _name; }; } /* namespace nut */ #endif /* __cplusplus */ /* End of C++ nutclient library declaration */ /* Begin of C nutclient library declaration */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * Array of string manipulation functions. * \{ */ /** Array of string.*/ typedef char** strarr; /** * Alloc an array of string. */ strarr strarr_alloc(unsigned short count); /** * Free an array of string. */ void strarr_free(strarr arr); /** * Nut general client types and functions. * \{ */ /** Hidden structure representing a connection to NUTD. */ typedef void* NUTCLIENT_t; /** * Destroy a client. * \param client Nut client handle. */ void nutclient_destroy(NUTCLIENT_t client); /** * Authenticate into the server. * \param client Nut client handle. * \param login User name. * \param passwd Password. */ void nutclient_authenticate(NUTCLIENT_t client, const char* login, const char* passwd); /** * Log out from server. * \param client Nut client handle. */ void nutclient_logout(NUTCLIENT_t client); /** * Register current user on the device. * \param client Nut client handle. * \param dev Device name to test. */ void nutclient_device_login(NUTCLIENT_t client, const char* dev); /** * Retrieve the number of users registered on a device. * \param client Nut client handle. * \param dev Device name to test. */ int nutclient_get_device_num_logins(NUTCLIENT_t client, const char* dev); /** * Set current user as master user of the device. * \param client Nut client handle. * \param dev Device name to test. */ void nutclient_device_master(NUTCLIENT_t client, const char* dev); /** * Set the FSD flag for the device. * \param client Nut client handle. * \param dev Device name to test. */ void nutclient_device_forced_shutdown(NUTCLIENT_t client, const char* dev); /** * Retrieve the list of devices of a client. * \param client Nut client handle. * \return Array of string containing device names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_devices(NUTCLIENT_t client); /** * Test if a device is supported by the client. * \param client Nut client handle. * \param dev Device name to test. * \return 1 if supported, 0 otherwise. */ int nutclient_has_device(NUTCLIENT_t client, const char* dev); /** * Intend to retrieve device description. * \param client Nut client handle. * \param dev Device name to test. * \return Description of device. Must be freed after use. */ char* nutclient_get_device_description(NUTCLIENT_t client, const char* dev); /** * Intend to retrieve device variable names. * \param client Nut client handle. * \param dev Device name. * \return Array of string containing variable names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_variables(NUTCLIENT_t client, const char* dev); /** * Intend to retrieve device read/write variable names. * \param client Nut client handle. * \param dev Device name. * \return Array of string containing read/write variable names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_rw_variables(NUTCLIENT_t client, const char* dev); /** * Test if a variable is supported by the device and the client. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \return 1 if supported, 0 otherwise. */ int nutclient_has_device_variable(NUTCLIENT_t client, const char* dev, const char* var); /** * Intend to retrieve device variable description. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \return Description of device variable. Must be freed after use. */ char* nutclient_get_device_variable_description(NUTCLIENT_t client, const char* dev, const char* var); /** * Intend to retrieve device variable values. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \return Array of string containing variable values. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var); /** * Intend to set device variable value. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \param value Value to set. */ void nutclient_set_device_variable_value(NUTCLIENT_t client, const char* dev, const char* var, const char* value); /** * Intend to set device variable multiple values. * \param client Nut client handle. * \param dev Device name. * \param var Variable name. * \param values Values to set. The cller is responsible to free it after call. */ void nutclient_set_device_variable_values(NUTCLIENT_t client, const char* dev, const char* var, const strarr values); /** * Intend to retrieve device command names. * \param client Nut client handle. * \param dev Device name. * \return Array of string containing command names. Must be freed with strarr_free(strarr). */ strarr nutclient_get_device_commands(NUTCLIENT_t client, const char* dev); /** * Test if a command is supported by the device and the client. * \param client Nut client handle. * \param dev Device name. * \param cmd Command name. * \return 1 if supported, 0 otherwise. */ int nutclient_has_device_command(NUTCLIENT_t client, const char* dev, const char* cmd); /** * Intend to retrieve device command description. * \param client Nut client handle. * \param dev Device name. * \param cmd Command name. * \return Description of device command. Must be freed after use. */ char* nutclient_get_device_command_description(NUTCLIENT_t client, const char* dev, const char* cmd); /** * Intend to execute device command. * \param client Nut client handle. * \param dev Device name. * \param cmd Command name. */ void nutclient_execute_device_command(NUTCLIENT_t client, const char* dev, const char* cmd); /** \} */ /** * Nut TCP client dedicated types and functions * \{ */ /** * Hidden structure representing a TCP connection to NUTD. * NUTCLIENT_TCP_t is back compatible to NUTCLIENT_t. */ typedef NUTCLIENT_t NUTCLIENT_TCP_t; /** * Create a client to NUTD using a TCP connection. * \param host Host name to connect to. * \param port Host port. * \return New client or NULL if failed. */ NUTCLIENT_TCP_t nutclient_tcp_create_client(const char* host, unsigned short port); /** * Test if a nut TCP client is connected. * \param client Nut TCP client handle. * \return 1 if connected, 0 otherwise. */ int nutclient_tcp_is_connected(NUTCLIENT_TCP_t client); /** * Disconnect a nut TCP client. * \param client Nut TCP client handle. */ void nutclient_tcp_disconnect(NUTCLIENT_TCP_t client); /** * Intend to reconnect a nut TCP client. * \param client Nut TCP client handle. * \return 0 if correctly connected. * \todo Implement different error codes. */ int nutclient_tcp_reconnect(NUTCLIENT_TCP_t client); /** * Set the timeout value for the TCP connection. * \param timeout Timeout in seconds, negative for blocking. */ void nutclient_tcp_set_timeout(NUTCLIENT_TCP_t client, long timeout); /** * Retrieve the timeout value for the TCP connection. * \return Timeout value in seconds. */ long nutclient_tcp_get_timeout(NUTCLIENT_TCP_t client); /** \} */ #ifdef __cplusplus } #endif /* __cplusplus */ /* End of C nutclient library declaration */ #endif /* NUTCLIENT_HPP_SEEN */ nut-2.7.2/clients/status.h0000644000175000017500000000253612277355125012425 00000000000000/* status.h - translation of status abbreviations to descriptions Copyright (C) 1999 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif struct { char *name; char *desc; int severity; } stattab[] = { { "OFF", "OFF", 1 }, { "OL", "ONLINE", 0 }, { "OB", "ON BATTERY", 2 }, { "LB", "LOW BATTERY", 2 }, { "RB", "REPLACE BATTERY", 2 }, { "OVER", "OVERLOAD", 2 }, { "TRIM", "VOLTAGE TRIM", 1 }, { "BOOST", "VOLTAGE BOOST", 1 }, { "CAL", "CALIBRATION", 1 }, { "BYPASS", "BYPASS", 2 }, { NULL, NULL, 0 } }; #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/Makefile.am0000644000175000017500000000354012320055460012745 00000000000000# Network UPS Tools: clients # by default, link programs in this directory with libcommon.a LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS) if WITH_SSL LDADD += $(LIBSSL_LIBS) endif # Avoid per-target CFLAGS, because this will prevent re-use of object # files. In any case, CFLAGS are only -I options, so there is no harm, # but only add them if we really use the target. AM_CFLAGS = -I$(top_srcdir)/include if WITH_SSL AM_CFLAGS += $(LIBSSL_CFLAGS) endif if WITH_CGI AM_CFLAGS += $(LIBGD_CFLAGS) endif bin_PROGRAMS = upsc upslog upsrw upscmd dist_bin_SCRIPTS = upssched-cmd sbin_PROGRAMS = upsmon upssched lib_LTLIBRARIES = libupsclient.la libnutclient.la if WITH_DEV include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h endif if WITH_CGI cgiexec_PROGRAMS = upsstats.cgi upsimage.cgi upsset.cgi endif upsc_SOURCES = upsc.c upsclient.h upscmd_SOURCES = upscmd.c upsclient.h upsrw_SOURCES = upsrw.c upsclient.h upslog_SOURCES = upslog.c upsclient.h upslog.h upsmon_SOURCES = upsmon.c upsmon.h upsclient.h upssched_SOURCES = upssched.c upssched.h upssched_LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS) upsimage_cgi_SOURCES = upsimage.c upsclient.h upsimagearg.h cgilib.c cgilib.h upsimage_cgi_LDADD = $(LDADD) $(LIBGD_LDFLAGS) upsset_cgi_SOURCES = upsset.c upsclient.h cgilib.c cgilib.h upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \ upsimagearg.h cgilib.c cgilib.h # not LDADD. libupsclient_la_SOURCES = upsclient.c upsclient.h libupsclient_la_LIBADD = ../common/libcommonclient.la if WITH_SSL libupsclient_la_LIBADD += $(LIBSSL_LIBS) endif # libupsclient version information # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html libupsclient_la_LDFLAGS = -version-info 4:0:0 libnutclient_la_SOURCES = nutclient.h nutclient.cpp libnutclient_la_LDFLAGS = -version-info 0:0:0 nut-2.7.2/clients/upsmon.h0000644000175000017500000001165412301203176012406 00000000000000/* upsmon.h - headers and other useful things for upsmon.h Copyright (C) 2000 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* flags for ups->status */ #define ST_ONLINE (1 << 0) /* UPS is on line (OL) */ #define ST_ONBATT (1 << 1) /* UPS is on battery (OB) */ #define ST_LOWBATT (1 << 2) /* UPS has a low battery (LB) */ #define ST_FSD (1 << 3) /* master has set forced shutdown flag */ #define ST_MASTER (1 << 4) /* we are the master on this UPS */ #define ST_LOGIN (1 << 5) /* we are logged into this UPS */ #define ST_CONNECTED (1 << 6) /* upscli_connect returned OK */ /* required contents of flag file */ #define SDMAGIC "upsmon-shutdown-file" #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* UPS tracking structure */ typedef struct { UPSCONN_t conn; /* upsclient state descriptor */ char *sys; /* raw system name from .conf */ char *upsname; /* just upsname */ char *hostname; /* just hostname */ int port; /* just the port */ int pv; /* power value from conf */ char *un; /* username (optional for now) */ char *pw; /* password from conf */ int status; /* status (see flags above) */ int retain; /* tracks deletions at reload */ /* handle suppression of COMMOK and ONLINE at startup */ int commstate; /* these start at -1, and only */ int linestate; /* fire on a 0->1 transition */ time_t lastpoll; /* time of last successful poll */ time_t lastnoncrit; /* time of last non-crit poll */ time_t lastrbwarn; /* time of last REPLBATT warning*/ time_t lastncwarn; /* time of last NOCOMM warning */ void *next; } utype_t; /* notify identifiers */ #define NOTIFY_ONLINE 0 /* UPS went on-line */ #define NOTIFY_ONBATT 1 /* UPS went on battery */ #define NOTIFY_LOWBATT 2 /* UPS went to low battery */ #define NOTIFY_FSD 3 /* Master upsmon set FSD flag */ #define NOTIFY_COMMOK 4 /* Communication established */ #define NOTIFY_COMMBAD 5 /* Communication lost */ #define NOTIFY_SHUTDOWN 6 /* System shutdown in progress */ #define NOTIFY_REPLBATT 7 /* UPS battery needs to be replaced */ #define NOTIFY_NOCOMM 8 /* UPS hasn't been contacted in awhile */ #define NOTIFY_NOPARENT 9 /* privileged parent process died */ /* notify flag values */ #define NOTIFY_IGNORE (1 << 0) /* don't do anything */ #define NOTIFY_SYSLOG (1 << 1) /* send the msg to the syslog */ #define NOTIFY_WALL (1 << 2) /* send the msg to all users */ #define NOTIFY_EXEC (1 << 3) /* send the msg to NOTIFYCMD script */ /* flags are set to NOTIFY_SYSLOG | NOTIFY_WALL at program init */ /* the user can override with NOTIFYFLAGS in the upsmon.conf */ struct { int type; const char *name; char *msg; /* NULL until overridden */ const char *stockmsg; int flags; } notifylist[] = { { NOTIFY_ONLINE, "ONLINE", NULL, "UPS %s on line power", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_ONBATT, "ONBATT", NULL, "UPS %s on battery", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_LOWBATT, "LOWBATT", NULL, "UPS %s battery is low", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_FSD, "FSD", NULL, "UPS %s: forced shutdown in progress", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_COMMOK, "COMMOK", NULL, "Communications with UPS %s established", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_COMMBAD, "COMMBAD", NULL, "Communications with UPS %s lost", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_SHUTDOWN, "SHUTDOWN", NULL, "Auto logout and shutdown proceeding", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_REPLBATT, "REPLBATT", NULL, "UPS %s battery needs to be replaced", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_NOCOMM, "NOCOMM", NULL, "UPS %s is unavailable", NOTIFY_SYSLOG | NOTIFY_WALL }, { NOTIFY_NOPARENT, "NOPARENT", NULL, "upsmon parent process died - shutdown impossible", NOTIFY_SYSLOG | NOTIFY_WALL }, { 0, NULL, NULL, NULL, 0 } }; /* values for signals passed between processes */ #define SIGCMD_FSD SIGUSR1 #define SIGCMD_STOP SIGTERM #define SIGCMD_RELOAD SIGHUP /* various constants */ #define NET_TIMEOUT 10 /* wait 10 seconds max for upsd to respond */ #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/upsmon.c0000644000175000017500000012626312301203176012404 00000000000000/* upsmon - monitor power status over the 'net (talks to upsd via TCP) Copyright (C) 1998 Russell Kroll 2012 Arnaud Quette This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include #include #include #include "upsclient.h" #include "upsmon.h" #include "parseconf.h" #include "timehead.h" #ifdef HAVE_STDARG_H #include #endif static char *shutdowncmd = NULL, *notifycmd = NULL; static char *powerdownflag = NULL, *configfile = NULL; static int minsupplies = 1, sleepval = 5, deadtime = 15; /* default polling interval = 5 sec */ static int pollfreq = 5, pollfreqalert = 5; /* slave hosts are given 15 sec by default to logout from upsd */ static int hostsync = 15; /* sum of all power values from config file */ static int totalpv = 0; /* default replace battery warning interval (seconds) */ static int rbwarntime = 43200; /* default "all communications down" warning interval (seconds) */ static int nocommwarntime = 300; /* default interval between the shutdown warning and the shutdown */ static int finaldelay = 5; /* set by SIGHUP handler, cleared after reload finishes */ static int reload_flag = 0; /* set after SIGINT, SIGQUIT, or SIGTERM */ static int exit_flag = 0; /* userid for unprivileged process when using fork mode */ static char *run_as_user = NULL; /* SSL details - where to find certs, whether to use them */ static char *certpath = NULL; static char *certname = NULL; static char *certpasswd = NULL; static int certverify = 0; /* don't verify by default */ static int forcessl = 0; /* don't require ssl by default */ static int userfsd = 0, use_pipe = 1, pipefd[2]; static utype_t *firstups = NULL; static int opt_af = AF_UNSPEC; /* signal handling things */ static struct sigaction sa; static sigset_t nut_upsmon_sigmask; static void setflag(int *val, int flag) { *val |= flag; } static void clearflag(int *val, int flag) { *val ^= (*val & flag); } static int flag_isset(int num, int flag) { return ((num & flag) == flag); } static void wall(const char *text) { FILE *wf; wf = popen("wall", "w"); if (!wf) { upslog_with_errno(LOG_NOTICE, "Can't invoke wall"); return; } fprintf(wf, "%s\n", text); pclose(wf); } static void notify(const char *notice, int flags, const char *ntype, const char *upsname) { char exec[LARGEBUF]; int ret; if (flag_isset(flags, NOTIFY_IGNORE)) return; if (flag_isset(flags, NOTIFY_SYSLOG)) upslogx(LOG_NOTICE, "%s", notice); /* fork here so upsmon doesn't get wedged if the notifier is slow */ ret = fork(); if (ret < 0) { upslog_with_errno(LOG_ERR, "Can't fork to notify"); return; } if (ret != 0) /* parent */ return; /* child continues and does all the work */ if (flag_isset(flags, NOTIFY_WALL)) wall(notice); if (flag_isset(flags, NOTIFY_EXEC)) { if (notifycmd != NULL) { snprintf(exec, sizeof(exec), "%s \"%s\"", notifycmd, notice); if (upsname) setenv("UPSNAME", upsname, 1); else setenv("UPSNAME", "", 1); setenv("NOTIFYTYPE", ntype, 1); if (system(exec) == -1) { upslog_with_errno(LOG_ERR, "%s", __func__); } } } exit(EXIT_SUCCESS); } static void do_notify(const utype_t *ups, int ntype) { int i; char msg[SMALLBUF], *upsname = NULL; /* grab this for later */ if (ups) upsname = ups->sys; for (i = 0; notifylist[i].name != NULL; i++) { if (notifylist[i].type == ntype) { upsdebugx(2, "%s: ntype 0x%04x (%s)", __func__, ntype, notifylist[i].name); snprintf(msg, sizeof(msg), notifylist[i].msg ? notifylist[i].msg : notifylist[i].stockmsg, ups ? ups->sys : ""); notify(msg, notifylist[i].flags, notifylist[i].name, upsname); return; } } /* not found ?! */ } /* check for master permissions on the server for this ups */ static int checkmaster(utype_t *ups) { char buf[SMALLBUF]; /* don't bother if we're not configured as a master for this ups */ if (!flag_isset(ups->status, ST_MASTER)) return 1; /* this shouldn't happen (LOGIN checks it earlier) */ if ((ups->upsname == NULL) || (strlen(ups->upsname) == 0)) { upslogx(LOG_ERR, "Set master on UPS [%s] failed: empty upsname", ups->sys); return 0; } snprintf(buf, sizeof(buf), "MASTER %s\n", ups->upsname); if (upscli_sendline(&ups->conn, buf, strlen(buf)) < 0) { upslogx(LOG_ALERT, "Can't set master mode on UPS [%s] - %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } if (upscli_readline(&ups->conn, buf, sizeof(buf)) == 0) { if (!strncmp(buf, "OK", 2)) return 1; /* not ERR, but not caught by readline either? */ upslogx(LOG_ALERT, "Master privileges unavailable on UPS [%s]", ups->sys); upslogx(LOG_ALERT, "Response: [%s]", buf); } else { /* something caught by readraw's parsing call */ upslogx(LOG_ALERT, "Master privileges unavailable on UPS [%s]", ups->sys); upslogx(LOG_ALERT, "Reason: %s", upscli_strerror(&ups->conn)); } return 0; } /* authenticate to upsd, plus do LOGIN and MASTER if applicable */ static int do_upsd_auth(utype_t *ups) { char buf[SMALLBUF]; if (!ups->un) { upslogx(LOG_ERR, "UPS [%s]: no username defined!", ups->sys); return 0; } snprintf(buf, sizeof(buf), "USERNAME %s\n", ups->un); if (upscli_sendline(&ups->conn, buf, strlen(buf)) < 0) { upslogx(LOG_ERR, "Can't set username on [%s]: %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } if (upscli_readline(&ups->conn, buf, sizeof(buf)) < 0) { upslogx(LOG_ERR, "Set username on [%s] failed: %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } /* authenticate first */ snprintf(buf, sizeof(buf), "PASSWORD %s\n", ups->pw); if (upscli_sendline(&ups->conn, buf, strlen(buf)) < 0) { upslogx(LOG_ERR, "Can't set password on [%s]: %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } if (upscli_readline(&ups->conn, buf, sizeof(buf)) < 0) { upslogx(LOG_ERR, "Set password on [%s] failed: %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } /* catch insanity from the server - not ERR and not OK either */ if (strncmp(buf, "OK", 2) != 0) { upslogx(LOG_ERR, "Set password on [%s] failed - got [%s]", ups->sys, buf); return 0; } /* we require a upsname now */ if ((ups->upsname == NULL) || (strlen(ups->upsname) == 0)) { upslogx(LOG_ERR, "Login to UPS [%s] failed: empty upsname", ups->sys); return 0; } /* password is set, let's login */ snprintf(buf, sizeof(buf), "LOGIN %s\n", ups->upsname); if (upscli_sendline(&ups->conn, buf, strlen(buf)) < 0) { upslogx(LOG_ERR, "Login to UPS [%s] failed: %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } if (upscli_readline(&ups->conn, buf, sizeof(buf)) < 0) { upslogx(LOG_ERR, "Can't login to UPS [%s]: %s", ups->sys, upscli_strerror(&ups->conn)); return 0; } /* catch insanity from the server - not ERR and not OK either */ if (strncmp(buf, "OK", 2) != 0) { upslogx(LOG_ERR, "Login on UPS [%s] failed - got [%s]", ups->sys, buf); return 0; } /* finally - everything is OK */ upsdebugx(1, "Logged into UPS %s", ups->sys); setflag(&ups->status, ST_LOGIN); /* now see if we also need to test master permissions */ return checkmaster(ups); } /* set flags and make announcements when a UPS has been checked successfully */ static void ups_is_alive(utype_t *ups) { time_t now; time(&now); ups->lastpoll = now; if (ups->commstate == 1) /* already known */ return; /* only notify for 0->1 transitions (to ignore the first connect) */ if (ups->commstate == 0) do_notify(ups, NOTIFY_COMMOK); ups->commstate = 1; } /* handle all the notifications for a missing UPS in one place */ static void ups_is_gone(utype_t *ups) { time_t now; /* first time: clear the flag and throw the first notifier */ if (ups->commstate != 0) { ups->commstate = 0; /* COMMBAD is the initial loss of communications */ do_notify(ups, NOTIFY_COMMBAD); return; } time(&now); /* first only act if we're seconds past the last poll */ if ((now - ups->lastpoll) < nocommwarntime) return; /* now only complain if we haven't lately */ if ((now - ups->lastncwarn) > nocommwarntime) { /* NOCOMM indicates a persistent condition */ do_notify(ups, NOTIFY_NOCOMM); ups->lastncwarn = now; } } static void ups_on_batt(utype_t *ups) { if (flag_isset(ups->status, ST_ONBATT)) { /* no change */ upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); return; } sleepval = pollfreqalert; /* bump up polling frequency */ ups->linestate = 0; upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); /* must have changed from OL to OB, so notify */ do_notify(ups, NOTIFY_ONBATT); setflag(&ups->status, ST_ONBATT); clearflag(&ups->status, ST_ONLINE); } static void ups_on_line(utype_t *ups) { if (flag_isset(ups->status, ST_ONLINE)) { /* no change */ upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); return; } sleepval = pollfreq; upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); /* ignore the first OL at startup, otherwise send the notifier */ if (ups->linestate != -1) do_notify(ups, NOTIFY_ONLINE); ups->linestate = 1; setflag(&ups->status, ST_ONLINE); clearflag(&ups->status, ST_ONBATT); } /* create the flag file if necessary */ static void set_pdflag(void) { FILE *pdf; if (!powerdownflag) return; pdf = fopen(powerdownflag, "w"); if (!pdf) { upslogx(LOG_ERR, "Failed to create power down flag!"); return; } fprintf(pdf, "%s", SDMAGIC); fclose(pdf); } /* the actual shutdown procedure */ static void doshutdown(void) { int ret; /* this should probably go away at some point */ upslogx(LOG_CRIT, "Executing automatic power-fail shutdown"); wall("Executing automatic power-fail shutdown\n"); do_notify(NULL, NOTIFY_SHUTDOWN); sleep(finaldelay); /* in the pipe model, we let the parent do this for us */ if (use_pipe) { char ch; ch = 1; ret = write(pipefd[1], &ch, 1); } else { /* one process model = we do all the work here */ if (geteuid() != 0) upslogx(LOG_WARNING, "Not root, shutdown may fail"); set_pdflag(); ret = system(shutdowncmd); if (ret != 0) upslogx(LOG_ERR, "Unable to call shutdown command: %s", shutdowncmd); } exit(EXIT_SUCCESS); } /* set forced shutdown flag so other upsmons know what's going on here */ static void setfsd(utype_t *ups) { char buf[SMALLBUF]; int ret; /* this shouldn't happen */ if (!ups->upsname) { upslogx(LOG_ERR, "setfsd: programming error: no UPS name set [%s]", ups->sys); return; } upsdebugx(2, "Setting FSD on UPS %s", ups->sys); snprintf(buf, sizeof(buf), "FSD %s\n", ups->upsname); ret = upscli_sendline(&ups->conn, buf, strlen(buf)); if (ret < 0) { upslogx(LOG_ERR, "FSD set on UPS %s failed: %s", ups->sys, upscli_strerror(&ups->conn)); return; } ret = upscli_readline(&ups->conn, buf, sizeof(buf)); if (ret < 0) { upslogx(LOG_ERR, "FSD set on UPS %s failed: %s", ups->sys, upscli_strerror(&ups->conn)); return; } if (!strncmp(buf, "OK", 2)) return; /* protocol error: upsd said something other than "OK" */ upslogx(LOG_ERR, "FSD set on UPS %s failed: %s", ups->sys, buf); } static void set_alarm(void) { alarm(NET_TIMEOUT); } static void clear_alarm(void) { signal(SIGALRM, SIG_IGN); alarm(0); } static int get_var(utype_t *ups, const char *var, char *buf, size_t bufsize) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; /* this shouldn't happen */ if (!ups->upsname) { upslogx(LOG_ERR, "get_var: programming error: no UPS name set [%s]", ups->sys); return -1; } numq = 0; if (!strcmp(var, "numlogins")) { query[0] = "NUMLOGINS"; query[1] = ups->upsname; numq = 2; } if (!strcmp(var, "status")) { query[0] = "VAR"; query[1] = ups->upsname; query[2] = "ups.status"; numq = 3; } if (numq == 0) { upslogx(LOG_ERR, "get_var: programming error: var=%s", var); return -1; } upsdebugx(3, "%s: %s / %s", __func__, ups->sys, var); ret = upscli_get(&ups->conn, numq, query, &numa, &answer); if (ret < 0) { /* detect old upsd */ if (upscli_upserror(&ups->conn) == UPSCLI_ERR_UNKCOMMAND) { upslogx(LOG_ERR, "UPS [%s]: Too old to monitor", ups->sys); return -1; } /* some other error */ return -1; } if (numa < numq) { upslogx(LOG_ERR, "%s: Error: insufficient data " "(got %d args, need at least %d)", var, numa, numq); return -1; } snprintf(buf, bufsize, "%s", answer[numq]); return 0; } static void slavesync(void) { utype_t *ups; char temp[SMALLBUF]; time_t start, now; int maxlogins, logins; time(&start); for (;;) { maxlogins = 0; for (ups = firstups; ups != NULL; ups = ups->next) { /* only check login count on our master(s) */ if (!flag_isset(ups->status, ST_MASTER)) continue; set_alarm(); if (get_var(ups, "numlogins", temp, sizeof(temp)) >= 0) { logins = strtol(temp, (char **)NULL, 10); if (logins > maxlogins) maxlogins = logins; } clear_alarm(); } /* if no UPS has more than 1 login (us), then slaves are gone */ if (maxlogins <= 1) return; /* after HOSTSYNC seconds, assume slaves are stuck and bail */ time(&now); if ((now - start) > hostsync) { upslogx(LOG_INFO, "Host sync timer expired, forcing shutdown"); return; } usleep(250000); } } static void forceshutdown(void) { utype_t *ups; int isamaster = 0; upsdebugx(1, "Shutting down any UPSes in MASTER mode..."); /* set FSD on any "master" UPS entries (forced shutdown in progress) */ for (ups = firstups; ups != NULL; ups = ups->next) if (flag_isset(ups->status, ST_MASTER)) { isamaster = 1; setfsd(ups); } /* if we're not a master on anything, we should shut down now */ if (!isamaster) doshutdown(); /* must be the master now */ upsdebugx(1, "This system is a master... waiting for slave logout..."); /* wait up to HOSTSYNC seconds for slaves to logout */ slavesync(); /* time expired or all the slaves are gone, so shutdown */ doshutdown(); } static int is_ups_critical(utype_t *ups) { time_t now; /* FSD = the master is forcing a shutdown */ if (flag_isset(ups->status, ST_FSD)) return 1; /* not OB or not LB = not critical yet */ if ((!flag_isset(ups->status, ST_ONBATT)) || (!flag_isset(ups->status, ST_LOWBATT))) return 0; /* must be OB+LB now */ /* if we're a master, declare it critical so we set FSD on it */ if (flag_isset(ups->status, ST_MASTER)) return 1; /* must be a slave now */ /* FSD isn't set, so the master hasn't seen it yet */ time(&now); /* give the master up to HOSTSYNC seconds before shutting down */ if ((now - ups->lastnoncrit) > hostsync) { upslogx(LOG_WARNING, "Giving up on the master for UPS [%s]", ups->sys); return 1; } /* there's still time left */ return 0; } /* recalculate the online power value and see if things are still OK */ static void recalc(void) { utype_t *ups; int val_ol = 0; time_t now; time(&now); ups = firstups; while (ups != NULL) { /* promote dead UPSes that were last known OB to OB+LB */ if ((now - ups->lastpoll) > deadtime) if (flag_isset(ups->status, ST_ONBATT)) { upsdebugx(1, "Promoting dead UPS: %s", ups->sys); setflag(&ups->status, ST_LOWBATT); } /* note: we assume that a UPS that isn't critical must be OK * * * * this means a UPS we've never heard from is assumed OL * * whether this is really the best thing to do is undecided */ /* crit = (FSD) || (OB & LB) > HOSTSYNC seconds */ if (is_ups_critical(ups)) upsdebugx(1, "Critical UPS: %s", ups->sys); else val_ol += ups->pv; ups = ups->next; } upsdebugx(3, "Current power value: %d", val_ol); upsdebugx(3, "Minimum power value: %d", minsupplies); if (val_ol < minsupplies) forceshutdown(); } static void ups_low_batt(utype_t *ups) { if (flag_isset(ups->status, ST_LOWBATT)) { /* no change */ upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); return; } upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); /* must have changed from !LB to LB, so notify */ do_notify(ups, NOTIFY_LOWBATT); setflag(&ups->status, ST_LOWBATT); } static void upsreplbatt(utype_t *ups) { time_t now; time(&now); if ((now - ups->lastrbwarn) > rbwarntime) { do_notify(ups, NOTIFY_REPLBATT); ups->lastrbwarn = now; } } static void ups_fsd(utype_t *ups) { if (flag_isset(ups->status, ST_FSD)) { /* no change */ upsdebugx(4, "%s: %s (no change)", __func__, ups->sys); return; } upsdebugx(3, "%s: %s (first time)", __func__, ups->sys); /* must have changed from !FSD to FSD, so notify */ do_notify(ups, NOTIFY_FSD); setflag(&ups->status, ST_FSD); } /* cleanly close the connection to a given UPS */ static void drop_connection(utype_t *ups) { upsdebugx(2, "Dropping connection to UPS [%s]", ups->sys); ups->commstate = 0; ups->linestate = 0; clearflag(&ups->status, ST_LOGIN); clearflag(&ups->status, ST_CONNECTED); upscli_disconnect(&ups->conn); } /* change some UPS parameters during reloading */ static void redefine_ups(utype_t *ups, int pv, const char *un, const char *pw, const char *master) { ups->retain = 1; if (ups->pv != pv) { upslogx(LOG_INFO, "UPS [%s]: redefined power value to %d", ups->sys, pv); ups->pv = pv; } totalpv += ups->pv; if (ups->un) { if (strcmp(ups->un, un) != 0) { upslogx(LOG_INFO, "UPS [%s]: redefined username", ups->sys); free(ups->un); ups->un = xstrdup(un); /* * if not logged in force a reconnection since this * may have been redefined to make a login work */ if (!flag_isset(ups->status, ST_LOGIN)) { upslogx(LOG_INFO, "UPS [%s]: retrying connection", ups->sys); drop_connection(ups); } } /* if (strcmp(ups->un, un) != 0) { */ } else { /* adding a username? (going to new style MONITOR line) */ if (un) { upslogx(LOG_INFO, "UPS [%s]: defined username", ups->sys); ups->un = xstrdup(un); /* possibly force reconnection - see above */ if (!flag_isset(ups->status, ST_LOGIN)) { upslogx(LOG_INFO, "UPS [%s]: retrying connection", ups->sys); drop_connection(ups); } } /* if (un) */ } /* paranoia */ if (!ups->pw) ups->pw = xstrdup(""); /* give it a bogus, but non-NULL one */ /* obviously don't put the new password in the syslog... */ if (strcmp(ups->pw, pw) != 0) { upslogx(LOG_INFO, "UPS [%s]: redefined password", ups->sys); free(ups->pw); ups->pw = xstrdup(pw); /* possibly force reconnection - see above */ if (!flag_isset(ups->status, ST_LOGIN)) { upslogx(LOG_INFO, "UPS [%s]: retrying connection", ups->sys); drop_connection(ups); } } /* slave -> master */ if ((!strcasecmp(master, "master")) && (!flag_isset(ups->status, ST_MASTER))) { upslogx(LOG_INFO, "UPS [%s]: redefined as master", ups->sys); setflag(&ups->status, ST_MASTER); /* reset connection to ensure master mode gets checked */ drop_connection(ups); return; } /* master -> slave */ if ((!strcasecmp(master, "slave")) && (flag_isset(ups->status, ST_MASTER))) { upslogx(LOG_INFO, "UPS [%s]: redefined as slave", ups->sys); clearflag(&ups->status, ST_MASTER); return; } } static void addups(int reloading, const char *sys, const char *pvs, const char *un, const char *pw, const char *master) { int pv; utype_t *tmp, *last; /* the username is now required - no more host-based auth */ if ((!sys) || (!pvs) || (!pw) || (!master) || (!un)) { upslogx(LOG_WARNING, "Ignoring invalid MONITOR line in %s!", configfile); upslogx(LOG_WARNING, "MONITOR configuration directives require five arguments."); return; } pv = strtol(pvs, (char **) NULL, 10); if (pv < 0) { upslogx(LOG_WARNING, "UPS [%s]: ignoring invalid power value [%s]", sys, pvs); return; } last = tmp = firstups; while (tmp) { last = tmp; /* check for duplicates */ if (!strcmp(tmp->sys, sys)) { if (reloading) redefine_ups(tmp, pv, un, pw, master); else upslogx(LOG_WARNING, "Warning: ignoring duplicate" " UPS [%s]", sys); return; } tmp = tmp->next; } tmp = xmalloc(sizeof(utype_t)); tmp->sys = xstrdup(sys); tmp->pv = pv; /* build this up so the user doesn't run with bad settings */ totalpv += tmp->pv; if (un) tmp->un = xstrdup(un); else tmp->un = NULL; tmp->pw = xstrdup(pw); tmp->status = 0; tmp->retain = 1; /* ignore initial COMMOK and ONLINE by default */ tmp->commstate = -1; tmp->linestate = -1; tmp->lastpoll = 0; tmp->lastnoncrit = 0; tmp->lastrbwarn = 0; tmp->lastncwarn = 0; if (!strcasecmp(master, "master")) setflag(&tmp->status, ST_MASTER); tmp->next = NULL; if (last) last->next = tmp; else firstups = tmp; if (tmp->pv) upslogx(LOG_INFO, "UPS: %s (%s) (power value %d)", tmp->sys, flag_isset(tmp->status, ST_MASTER) ? "master" : "slave", tmp->pv); else upslogx(LOG_INFO, "UPS: %s (monitoring only)", tmp->sys); tmp->upsname = tmp->hostname = NULL; if (upscli_splitname(tmp->sys, &tmp->upsname, &tmp->hostname, &tmp->port) != 0) { upslogx(LOG_ERR, "Error: unable to split UPS name [%s]", tmp->sys); } if (!tmp->upsname) upslogx(LOG_WARNING, "Warning: UPS [%s]: no upsname set!", tmp->sys); } static void set_notifymsg(const char *name, const char *msg) { int i; for (i = 0; notifylist[i].name != NULL; i++) { if (!strcasecmp(notifylist[i].name, name)) { free(notifylist[i].msg); notifylist[i].msg = xstrdup(msg); return; } } upslogx(LOG_WARNING, "'%s' is not a valid notify event name", name); } static void set_notifyflag(const char *ntype, char *flags) { int i, pos; char *ptr, *tmp; /* find ntype */ pos = -1; for (i = 0; notifylist[i].name != NULL; i++) { if (!strcasecmp(notifylist[i].name, ntype)) { pos = i; break; } } if (pos == -1) { upslogx(LOG_WARNING, "Warning: invalid notify type [%s]", ntype); return; } ptr = flags; /* zero existing flags */ notifylist[pos].flags = 0; while (ptr) { int newflag; tmp = strchr(ptr, '+'); if (tmp) *tmp++ = '\0'; newflag = 0; if (!strcmp(ptr, "SYSLOG")) newflag = NOTIFY_SYSLOG; if (!strcmp(ptr, "WALL")) newflag = NOTIFY_WALL; if (!strcmp(ptr, "EXEC")) newflag = NOTIFY_EXEC; if (!strcmp(ptr, "IGNORE")) newflag = NOTIFY_IGNORE; if (newflag) notifylist[pos].flags |= newflag; else upslogx(LOG_WARNING, "Invalid notify flag: [%s]", ptr); ptr = tmp; } } /* in split mode, the parent doesn't hear about reloads */ static void checkmode(char *cfgentry, char *oldvalue, char *newvalue, int reloading) { /* nothing to do if in "all as root" mode */ if (use_pipe == 0) return; /* it's ok if we're not reloading yet */ if (reloading == 0) return; /* also nothing to do if it didn't change */ if ((oldvalue) && (newvalue)) { if (!strcmp(oldvalue, newvalue)) return; } /* otherwise, yell at them */ upslogx(LOG_WARNING, "Warning: %s redefined in split-process mode!", cfgentry); upslogx(LOG_WARNING, "You must restart upsmon for this change to work"); } /* returns 1 if used, 0 if not, so we can complain about bogus configs */ static int parse_conf_arg(int numargs, char **arg) { /* using up to arg[1] below */ if (numargs < 2) return 0; /* SHUTDOWNCMD */ if (!strcmp(arg[0], "SHUTDOWNCMD")) { checkmode(arg[0], shutdowncmd, arg[1], reload_flag); free(shutdowncmd); shutdowncmd = xstrdup(arg[1]); return 1; } /* POWERDOWNFLAG */ if (!strcmp(arg[0], "POWERDOWNFLAG")) { checkmode(arg[0], powerdownflag, arg[1], reload_flag); free(powerdownflag); powerdownflag = xstrdup(arg[1]); if (!reload_flag) upslogx(LOG_INFO, "Using power down flag file %s", arg[1]); return 1; } /* NOTIFYCMD */ if (!strcmp(arg[0], "NOTIFYCMD")) { free(notifycmd); notifycmd = xstrdup(arg[1]); return 1; } /* POLLFREQ */ if (!strcmp(arg[0], "POLLFREQ")) { pollfreq = atoi(arg[1]); return 1; } /* POLLFREQALERT */ if (!strcmp(arg[0], "POLLFREQALERT")) { pollfreqalert = atoi(arg[1]); return 1; } /* HOSTSYNC */ if (!strcmp(arg[0], "HOSTSYNC")) { hostsync = atoi(arg[1]); return 1; } /* DEADTIME */ if (!strcmp(arg[0], "DEADTIME")) { deadtime = atoi(arg[1]); return 1; } /* MINSUPPLIES */ if (!strcmp(arg[0], "MINSUPPLIES")) { minsupplies = atoi(arg[1]); return 1; } /* RBWARNTIME */ if (!strcmp(arg[0], "RBWARNTIME")) { rbwarntime = atoi(arg[1]); return 1; } /* NOCOMMWARNTIME */ if (!strcmp(arg[0], "NOCOMMWARNTIME")) { nocommwarntime = atoi(arg[1]); return 1; } /* FINALDELAY */ if (!strcmp(arg[0], "FINALDELAY")) { finaldelay = atoi(arg[1]); return 1; } /* RUN_AS_USER */ if (!strcmp(arg[0], "RUN_AS_USER")) { free(run_as_user); run_as_user = xstrdup(arg[1]); return 1; } /* CERTPATH */ if (!strcmp(arg[0], "CERTPATH")) { free(certpath); certpath = xstrdup(arg[1]); return 1; } /* CERTVERIFY (0|1) */ if (!strcmp(arg[0], "CERTVERIFY")) { certverify = atoi(arg[1]); return 1; } /* FORCESSL (0|1) */ if (!strcmp(arg[0], "FORCESSL")) { forcessl = atoi(arg[1]); return 1; } /* using up to arg[2] below */ if (numargs < 3) return 0; /* NOTIFYMSG */ if (!strcmp(arg[0], "NOTIFYMSG")) { set_notifymsg(arg[1], arg[2]); return 1; } /* NOTIFYFLAG */ if (!strcmp(arg[0], "NOTIFYFLAG")) { set_notifyflag(arg[1], arg[2]); return 1; } /* CERTIDENT */ if (!strcmp(arg[0], "CERTIDENT")) { free(certname); certname = xstrdup(arg[1]); free(certpasswd); certpasswd = xstrdup(arg[2]); return 1; } /* using up to arg[4] below */ if (numargs < 5) return 0; /* CERTHOST (0|1) (0|1) */ if (!strcmp(arg[0], "CERTHOST")) { upscli_add_host_cert(arg[1], arg[2], atoi(arg[3]), atoi(arg[4])); return 1; } if (!strcmp(arg[0], "MONITOR")) { /* original style: no username (only 5 args) */ if (numargs == 5) { upslogx(LOG_ERR, "Unable to use old-style MONITOR line without a username"); upslogx(LOG_ERR, "Convert it and add a username to upsd.users - see the documentation"); fatalx(EXIT_FAILURE, "Fatal error: unusable configuration"); } /* ("master" | "slave") */ addups(reload_flag, arg[1], arg[2], arg[3], arg[4], arg[5]); return 1; } /* didn't parse it at all */ return 0; } /* called for fatal errors in parseconf like malloc failures */ static void upsmon_err(const char *errmsg) { upslogx(LOG_ERR, "Fatal error in parseconf(%s): %s", configfile, errmsg); } static void loadconfig(void) { PCONF_CTX_t ctx; pconf_init(&ctx, upsmon_err); if (!pconf_file_begin(&ctx, configfile)) { pconf_finish(&ctx); if (reload_flag == 1) { upslog_with_errno(LOG_ERR, "Reload failed: %s", ctx.errmsg); return; } fatalx(EXIT_FAILURE, "%s", ctx.errmsg); } while (pconf_file_next(&ctx)) { if (pconf_parse_error(&ctx)) { upslogx(LOG_ERR, "Parse error: %s:%d: %s", configfile, ctx.linenum, ctx.errmsg); continue; } if (ctx.numargs < 1) continue; if (!parse_conf_arg(ctx.numargs, ctx.arglist)) { unsigned int i; char errmsg[SMALLBUF]; snprintf(errmsg, sizeof(errmsg), "%s line %d: invalid directive", configfile, ctx.linenum); for (i = 0; i < ctx.numargs; i++) snprintfcat(errmsg, sizeof(errmsg), " %s", ctx.arglist[i]); upslogx(LOG_WARNING, "%s", errmsg); } } pconf_finish(&ctx); } /* SIGPIPE handler */ static void sigpipe(int sig) { upsdebugx(1, "SIGPIPE: dazed and confused, but continuing..."); } /* SIGQUIT, SIGTERM handler */ static void set_exit_flag(int sig) { exit_flag = sig; } static void ups_free(utype_t *ups) { free(ups->sys); free(ups->upsname); free(ups->hostname); free(ups->un); free(ups->pw); free(ups); } static void upsmon_cleanup(void) { int i; utype_t *utmp, *unext; /* close all fds */ utmp = firstups; while (utmp) { unext = utmp->next; drop_connection(utmp); ups_free(utmp); utmp = unext; } free(run_as_user); free(shutdowncmd); free(notifycmd); free(powerdownflag); for (i = 0; notifylist[i].name != NULL; i++) { free(notifylist[i].msg); } upscli_cleanup(); } static void user_fsd(int sig) { upslogx(LOG_INFO, "Signal %d: User requested FSD", sig); userfsd = 1; } static void set_reload_flag(int sig) { reload_flag = 1; } /* handler for alarm when getupsvarfd times out */ static void read_timeout(int sig) { /* don't do anything here, just return */ } /* install handlers for a few signals */ static void setup_signals(void) { sigemptyset(&nut_upsmon_sigmask); sa.sa_mask = nut_upsmon_sigmask; sa.sa_flags = 0; sa.sa_handler = sigpipe; sigaction(SIGPIPE, &sa, NULL); sa.sa_handler = set_exit_flag; sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); /* handle timeouts */ sa.sa_handler = read_timeout; sigaction(SIGALRM, &sa, NULL); /* deal with the ones from userspace as well */ sa.sa_handler = user_fsd; sigaction(SIGCMD_FSD, &sa, NULL); sa.sa_handler = set_reload_flag; sigaction(SIGCMD_RELOAD, &sa, NULL); } /* remember the last time the ups was not critical (OB + LB) */ static void update_crittimer(utype_t *ups) { /* if !OB or !LB, then it's not critical, so log the time */ if ((!flag_isset(ups->status, ST_ONBATT)) || (!flag_isset(ups->status, ST_LOWBATT))) { time(&ups->lastnoncrit); return; } /* fallthrough: let the timer age */ } /* handle connecting to upsd, plus get SSL going too if possible */ static int try_connect(utype_t *ups) { int flags = 0, ret; upsdebugx(1, "Trying to connect to UPS [%s]", ups->sys); clearflag(&ups->status, ST_CONNECTED); /* force it if configured that way, just try it otherwise */ if (forcessl == 1) flags |= UPSCLI_CONN_REQSSL; else flags |= UPSCLI_CONN_TRYSSL; if (opt_af == AF_INET) flags |= UPSCLI_CONN_INET; if (opt_af == AF_INET6) flags |= UPSCLI_CONN_INET6; if (!certpath) { if (certverify == 1) { upslogx(LOG_ERR, "Configuration error: " "CERTVERIFY is set, but CERTPATH isn't"); upslogx(LOG_ERR, "UPS [%s]: Connection impossible, " "dropping link", ups->sys); ups_is_gone(ups); drop_connection(ups); return 0; /* failed */ } } if (certverify == 1) { flags |= UPSCLI_CONN_CERTVERIF; } ret = upscli_connect(&ups->conn, ups->hostname, ups->port, flags); if (ret < 0) { upslogx(LOG_ERR, "UPS [%s]: connect failed: %s", ups->sys, upscli_strerror(&ups->conn)); ups_is_gone(ups); return 0; } /* we're definitely connected now */ setflag(&ups->status, ST_CONNECTED); /* now try to authenticate to upsd */ ret = do_upsd_auth(ups); if (ret == 1) return 1; /* everything is happy */ /* something failed in the auth so we may not be completely logged in */ /* FUTURE: do something beyond the error msgs from do_upsd_auth? */ return 0; } /* deal with the contents of STATUS or ups.status for this ups */ static void parse_status(utype_t *ups, char *status) { char *statword, *ptr; clear_alarm(); upsdebugx(2, "%s: [%s]", __func__, status); /* empty response is the same as a dead ups */ if (!strcmp(status, "")) { ups_is_gone(ups); return; } ups_is_alive(ups); /* clear these out early if they disappear */ if (!strstr(status, "LB")) clearflag(&ups->status, ST_LOWBATT); if (!strstr(status, "FSD")) clearflag(&ups->status, ST_FSD); statword = status; /* split up the status words and parse each one separately */ while (statword != NULL) { ptr = strchr(statword, ' '); if (ptr) *ptr++ = '\0'; upsdebugx(3, "parsing: [%s]", statword); if (!strcasecmp(statword, "OL")) ups_on_line(ups); if (!strcasecmp(statword, "OB")) ups_on_batt(ups); if (!strcasecmp(statword, "LB")) ups_low_batt(ups); if (!strcasecmp(statword, "RB")) upsreplbatt(ups); /* do it last to override any possible OL */ if (!strcasecmp(statword, "FSD")) ups_fsd(ups); update_crittimer(ups); statword = ptr; } } /* see what the status of the UPS is and handle any changes */ static void pollups(utype_t *ups) { char status[SMALLBUF]; /* try a reconnect here */ if (!flag_isset(ups->status, ST_CONNECTED)) if (try_connect(ups) != 1) return; if (upscli_ssl(&ups->conn) == 1) upsdebugx(2, "%s: %s [SSL]", __func__, ups->sys); else upsdebugx(2, "%s: %s", __func__, ups->sys); set_alarm(); if (get_var(ups, "status", status, sizeof(status)) == 0) { clear_alarm(); parse_status(ups, status); return; } /* fallthrough: no communications */ clear_alarm(); /* try to make some of these a little friendlier */ switch (upscli_upserror(&ups->conn)) { case UPSCLI_ERR_UNKNOWNUPS: upslogx(LOG_ERR, "Poll UPS [%s] failed - [%s] " "does not exist on server %s", ups->sys, ups->upsname, ups->hostname); break; default: upslogx(LOG_ERR, "Poll UPS [%s] failed - %s", ups->sys, upscli_strerror(&ups->conn)); break; } /* throw COMMBAD or NOCOMM as conditions may warrant */ ups_is_gone(ups); /* if upsclient lost the connection, clean up things on our side */ if (upscli_fd(&ups->conn) == -1) { drop_connection(ups); return; } } /* see if the powerdownflag file is there and proper */ static int pdflag_status(void) { FILE *pdf; char buf[SMALLBUF]; if (!powerdownflag) return 0; /* unusable */ pdf = fopen(powerdownflag, "r"); if (pdf == NULL) return 0; /* not there */ /* if it exists, see if it has the right text in it */ if (fgets(buf, sizeof(buf), pdf) == NULL) { upslog_with_errno(LOG_ERR, "'%s' exists, but we can't read from it", powerdownflag); } fclose(pdf); /* reasoning: say upsmon.conf is world-writable (!) and some nasty * user puts something "important" as the power flag file. This * keeps upsmon from utterly trashing it when starting up or powering * down at the expense of not shutting down the UPS. * * solution: don't let mere mortals edit that configuration file. */ if (!strncmp(buf, SDMAGIC, strlen(SDMAGIC))) return 1; /* exists and looks good */ return -1; /* error: something else is in there */ } /* only remove the flag file if it's actually from us */ static void clear_pdflag(void) { int ret; ret = pdflag_status(); if (ret == -1) { upslogx(LOG_ERR, "POWERDOWNFLAG (%s) does not contain" "the upsmon magic string - disabling!", powerdownflag); powerdownflag = NULL; return; } /* it's from us, so we can remove it */ if (ret == 1) unlink(powerdownflag); } /* exit with success only if it exists and is proper */ static int check_pdflag(void) { int ret; ret = pdflag_status(); if (ret == -1) { upslogx(LOG_ERR, "POWERDOWNFLAG (%s) does not contain " "the upsmon magic string", powerdownflag); return EXIT_FAILURE; } if (ret == 0) { /* not there - this is not a shutdown event */ upslogx(LOG_ERR, "Power down flag is not set"); return EXIT_FAILURE; } if (ret != 1) { upslogx(LOG_ERR, "Programming error: pdflag_status returned %d", ret); return EXIT_FAILURE; } /* only thing left - must be time for a shutdown */ upslogx(LOG_INFO, "Power down flag is set"); return EXIT_SUCCESS; } static void help(const char *progname) { printf("Monitors UPS servers and may initiate shutdown if necessary.\n\n"); printf("usage: %s [OPTIONS]\n\n", progname); printf(" -c send command to running process\n"); printf(" commands:\n"); printf(" - fsd: shutdown all master UPSes (use with caution)\n"); printf(" - reload: reread configuration\n"); printf(" - stop: stop monitoring and exit\n"); printf(" -D raise debugging level\n"); printf(" -h display this help\n"); printf(" -K checks POWERDOWNFLAG, sets exit code to 0 if set\n"); printf(" -p always run privileged (disable privileged parent)\n"); printf(" -u run child as user (ignored when using -p)\n"); printf(" -4 IPv4 only\n"); printf(" -6 IPv6 only\n"); exit(EXIT_SUCCESS); } static void runparent(int fd) { int ret; char ch; /* handling signals is the child's job */ signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); ret = read(fd, &ch, 1); if (ret < 1) { if (errno == ENOENT) fatalx(EXIT_FAILURE, "upsmon parent: exiting (child exited)"); fatal_with_errno(EXIT_FAILURE, "upsmon parent: read"); } if (ch != 1) fatalx(EXIT_FAILURE, "upsmon parent: got bogus pipe command %c", ch); /* have to do this here - child is unprivileged */ set_pdflag(); ret = system(shutdowncmd); if (ret != 0) upslogx(LOG_ERR, "parent: Unable to call shutdown command: %s", shutdowncmd); close(fd); exit(EXIT_SUCCESS); } /* fire up the split parent/child scheme */ static void start_pipe(void) { int ret; ret = pipe(pipefd); if (ret) fatal_with_errno(EXIT_FAILURE, "pipe creation failed"); ret = fork(); if (ret < 0) fatal_with_errno(EXIT_FAILURE, "fork failed"); /* start the privileged parent */ if (ret != 0) { close(pipefd[1]); runparent(pipefd[0]); exit(EXIT_FAILURE); /* NOTREACHED */ } close(pipefd[0]); } static void delete_ups(utype_t *target) { utype_t *ptr, *last; if (!target) return; ptr = last = firstups; while (ptr) { if (ptr == target) { upslogx(LOG_NOTICE, "No longer monitoring UPS [%s]", target->sys); /* disconnect cleanly */ drop_connection(ptr); /* about to delete the first ups? */ if (ptr == last) firstups = ptr->next; else last->next = ptr->next; /* release memory */ ups_free(ptr); return; } last = ptr; ptr = ptr->next; } /* shouldn't happen */ upslogx(LOG_ERR, "delete_ups: UPS not found"); } /* see if we can open a file */ static int check_file(const char *fn) { FILE *f; f = fopen(fn, "r"); if (!f) { upslog_with_errno(LOG_ERR, "Reload failed: can't open %s", fn); return 0; /* failed */ } fclose(f); return 1; /* OK */ } static void reload_conf(void) { utype_t *tmp, *next; upslogx(LOG_INFO, "Reloading configuration"); /* sanity check */ if (!check_file(configfile)) { reload_flag = 0; return; } /* flip through ups list, clear retain value */ tmp = firstups; while (tmp) { tmp->retain = 0; tmp = tmp->next; } /* reset paranoia checker */ totalpv = 0; /* reread upsmon.conf */ loadconfig(); /* go through the utype_t struct again */ tmp = firstups; while (tmp) { next = tmp->next; /* !retain means it wasn't in the .conf this time around */ if (tmp->retain == 0) delete_ups(tmp); tmp = next; } /* see if the user just blew off a foot */ if (totalpv < minsupplies) { upslogx(LOG_CRIT, "Fatal error: total power value (%d) less " "than MINSUPPLIES (%d)", totalpv, minsupplies); fatalx(EXIT_FAILURE, "Impossible power configuation, unable to continue"); } /* finally clear the flag */ reload_flag = 0; } /* make sure the parent is still alive */ static void check_parent(void) { int ret; fd_set rfds; struct timeval tv; time_t now; static time_t lastwarn = 0; FD_ZERO(&rfds); FD_SET(pipefd[1], &rfds); tv.tv_sec = 0; tv.tv_usec = 0; ret = select(pipefd[1] + 1, &rfds, NULL, NULL, &tv); if (ret == 0) return; /* this should never happen, but we MUST KNOW if it ever does */ time(&now); /* complain every 2 minutes */ if ((now - lastwarn) < 120) return; lastwarn = now; do_notify(NULL, NOTIFY_NOPARENT); /* also do this in case the notifier isn't being effective */ upslogx(LOG_ALERT, "Parent died - shutdown impossible"); } int main(int argc, char *argv[]) { const char *prog = xbasename(argv[0]); int i, cmd = 0, checking_flag = 0; printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); /* if no configuration file is specified on the command line, use default */ configfile = xmalloc(SMALLBUF); snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath()); configfile = xrealloc(configfile, strlen(configfile) + 1); run_as_user = xstrdup(RUN_AS_USER); while ((i = getopt(argc, argv, "+Dhic:f:pu:VK46")) != -1) { switch (i) { case 'c': if (!strncmp(optarg, "fsd", strlen(optarg))) cmd = SIGCMD_FSD; if (!strncmp(optarg, "stop", strlen(optarg))) cmd = SIGCMD_STOP; if (!strncmp(optarg, "reload", strlen(optarg))) cmd = SIGCMD_RELOAD; /* bad command name given */ if (cmd == 0) help(argv[0]); break; case 'D': nut_debug_level++; break; case 'f': free(configfile); configfile = xstrdup(optarg); break; case 'h': help(argv[0]); break; case 'K': checking_flag = 1; break; case 'p': use_pipe = 0; break; case 'u': free(run_as_user); run_as_user = xstrdup(optarg); break; case 'V': /* just show the banner */ exit(EXIT_SUCCESS); case '4': opt_af = AF_INET; break; case '6': opt_af = AF_INET6; break; default: help(argv[0]); break; } } if (cmd) { sendsignal(prog, cmd); exit(EXIT_SUCCESS); } /* otherwise, we are being asked to start. * so check if a previous instance is running by sending signal '0' * (Ie 'kill 0') */ if (sendsignal(prog, 0) == 0) { printf("Fatal error: A previous upsmon instance is already running!\n"); printf("Either stop the previous instance first, or use the 'reload' command.\n"); exit(EXIT_FAILURE); } argc -= optind; argv += optind; open_syslog(prog); loadconfig(); if (checking_flag) exit(check_pdflag()); if (shutdowncmd == NULL) printf("Warning: no shutdown command defined!\n"); /* we may need to get rid of a flag from a previous shutdown */ if (powerdownflag != NULL) clear_pdflag(); /* FIXME (else): POWERDOWNFLAG is not defined!! * => fallback to a default value */ if (totalpv < minsupplies) { printf("\nFatal error: insufficient power configured!\n\n"); printf("Sum of power values........: %d\n", totalpv); printf("Minimum value (MINSUPPLIES): %d\n", minsupplies); printf("\nEdit your upsmon.conf and change the values.\n"); exit(EXIT_FAILURE); } if (nut_debug_level < 1) { background(); } else { upsdebugx(1, "debug level is '%d'", nut_debug_level); } /* only do the pipe stuff if the user hasn't disabled it */ if (use_pipe) { struct passwd *new_uid = get_user_pwent(run_as_user); /* === root parent and unprivileged child split here === */ start_pipe(); /* write the pid file now, as we will soon lose root */ writepid(prog); become_user(new_uid); } else { upslogx(LOG_INFO, "Warning: running as one big root process by request (upsmon -p)"); writepid(prog); } if (upscli_init(certverify, certpath, certname, certpasswd) < 0) { exit(EXIT_FAILURE); } /* prep our signal handlers */ setup_signals(); /* reopen the log for the child process */ closelog(); open_syslog(prog); while (exit_flag == 0) { utype_t *ups; /* check flags from signal handlers */ if (userfsd) forceshutdown(); if (reload_flag) reload_conf(); for (ups = firstups; ups != NULL; ups = ups->next) pollups(ups); recalc(); /* make sure the parent hasn't died */ if (use_pipe) check_parent(); /* reap children that have exited */ waitpid(-1, NULL, WNOHANG); sleep(sleepval); } upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); upsmon_cleanup(); exit(EXIT_SUCCESS); } nut-2.7.2/clients/upssched-cmd0000755000175000017500000000101312277355125013223 00000000000000#! /bin/sh # # This script should be called by upssched via the CMDSCRIPT directive. # # Here is a quick example to show how to handle a bunch of possible # timer names with the help of the case structure. # # This script may be replaced with another program without harm. # # The first argument passed to your CMDSCRIPT is the name of the timer # from your AT lines. case $1 in upsgone) logger -t upssched-cmd "The UPS has been gone for awhile" ;; *) logger -t upssched-cmd "Unrecognized command: $1" ;; esac nut-2.7.2/clients/upsset.c0000644000175000017500000005647112277355125012427 00000000000000/* upsset - CGI program to manage read/write variables Copyright (C) 1999 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include #include #include #include #include "upsclient.h" #include "cgilib.h" #include "parseconf.h" struct list_t { char *name; struct list_t *next; }; /* see the stock upsset.conf for the whole rant on what this is */ #define MAGIC_ENABLE_STRING "I_HAVE_SECURED_MY_CGI_DIRECTORY" #define HARD_UPSVAR_LIMIT_NUM 64 #define HARD_UPSVAR_LIMIT_LEN 256 char *monups, *username, *password, *function, *upscommand; /* set once the MAGIC_ENABLE_STRING is found in the upsset.conf */ int magic_string_set = 0; static int port; static char *upsname, *hostname; static UPSCONN_t ups; typedef struct { char *var; char *value; void *next; } uvtype_t; uvtype_t *firstuv = NULL; void parsearg(char *var, char *value) { char *ptr; uvtype_t *last, *tmp = NULL; static int upsvc = 0; /* store variables from a SET command for the later commit */ if (!strncmp(var, "UPSVAR_", 7)) { /* if someone bombs us with variables, stop at some point */ if (upsvc > HARD_UPSVAR_LIMIT_NUM) return; /* same idea: throw out anything that's much too long */ if (strlen(value) > HARD_UPSVAR_LIMIT_LEN) return; ptr = strchr(var, '_'); if (!ptr) /* sanity check */ return; ptr++; tmp = last = firstuv; while (tmp) { last = tmp; tmp = tmp->next; } tmp = xmalloc(sizeof(uvtype_t)); tmp->var = xstrdup(ptr); tmp->value = xstrdup(value); tmp->next = NULL; if (last) last->next = tmp; else firstuv = tmp; upsvc++; return; } if (!strcmp(var, "username")) { free(username); username = xstrdup(value); } if (!strcmp(var, "password")) { free(password); password = xstrdup(value); } if (!strcmp(var, "function")) { free(function); function = xstrdup(value); } if (!strcmp(var, "monups")) { free(monups); monups = xstrdup(value); } if (!strcmp(var, "upscommand")) { free(upscommand); upscommand = xstrdup(value); } } static void do_header(const char *title) { printf("\n"); printf("\n"); printf("upsset: %s\n", title); printf("\n"); printf("\n"); printf("
\n"); } static void start_table(void) { printf("\n"); printf("\n"); } /* propagate login details across pages - no cookies here! */ static void do_hidden(const char *next) { printf("\n", username); printf("\n", password); if (next) printf("\n", next); } /* generate SELECT chooser from hosts.conf entries */ static void upslist_arg(int numargs, char **arg) { if (numargs < 3) return; /* MONITOR */ if (!strcmp(arg[0], "MONITOR")) { printf("\n", arg[2]); } } /* called for fatal errors in parseconf like malloc failures */ static void upsset_hosts_err(const char *errmsg) { upslogx(LOG_ERR, "Fatal error in parseconf(hosts.conf): %s", errmsg); } /* this defaults to wherever we are now, ups and function-wise */ static void do_pickups(const char *currfunc) { char hostfn[SMALLBUF]; PCONF_CTX_t ctx; snprintf(hostfn, sizeof(hostfn), "%s/hosts.conf", confpath()); printf("
\n"); printf("Select UPS and function:\n
\n"); pconf_init(&ctx, upsset_hosts_err); if (!pconf_file_begin(&ctx, hostfn)) { pconf_finish(&ctx); printf("Error: hosts.conf unavailable\n"); printf("\n"); /* stderr is for the admin - should wind up in error.log */ fprintf(stderr, "upsset: %s\n", ctx.errmsg); return; } printf("\n"); printf("\n"); do_hidden(NULL); printf("\n"); printf("\n"); } static void error_page(const char *next, const char *title, const char *fmt, ...) { char msg[SMALLBUF]; va_list ap; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); do_header(title); start_table(); printf("
\n"); printf("\n"); printf("
\n"); printf("Network UPS Tools upsset %s\n", UPS_VERSION); printf("
\n"); printf("Error: %s\n", msg); printf("
\n"); do_pickups(next); printf("
\n"); printf("
\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } static void loginscreen(void) { do_header("Login"); printf("
\n"); start_table(); printf("\n"); printf("Username\n"); printf("\n"); printf("\n"); printf("\n"); printf("Password\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } /* try to connect to upsd - generate an error page if it fails */ static void upsd_connect(void) { if (upscli_splitname(monups, &upsname, &hostname, &port) != 0) { error_page("showsettings", "UPS name is unusable", "Unable to split UPS name [%s]", monups); /* NOTREACHED */ } if (upscli_connect(&ups, hostname, port, 0) < 0) { error_page("showsettings", "Connect failure", "Unable to connect to %s: %s", monups, upscli_strerror(&ups)); /* NOTREACHED */ } } static void print_cmd(const char *cmd) { int ret; unsigned int numq, numa; char **answer; const char *query[4]; query[0] = "CMDDESC"; query[1] = upsname; query[2] = cmd; numq = 3; ret = upscli_get(&ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) return; /* CMDDESC */ printf("\n", cmd, answer[3]); } /* generate a list of instant commands */ static void showcmds(void) { int ret; unsigned int numq, numa; const char *query[2]; char **answer; struct list_t *lhead, *llast, *ltmp, *lnext; char *desc; if (!checkhost(monups, &desc)) error_page("showsettings", "Access denied", "Access to that host is not authorized"); upsd_connect(); llast = lhead = NULL; query[0] = "CMD"; query[1] = upsname; numq = 2; ret = upscli_list_start(&ups, numq, query); if (ret < 0) { fprintf(stderr, "LIST CMD %s failed: %s\n", upsname, upscli_strerror(&ups)); error_page("showcmds", "Server protocol error", "LIST CMD command failed"); /* NOTREACHED */ } ret = upscli_list_next(&ups, numq, query, &numa, &answer); while (ret == 1) { /* CMD upsname cmdname */ if (numa < 3) { fprintf(stderr, "Error: insufficient data " "(got %d args, need at least 3)\n", numa); return; } ltmp = xmalloc(sizeof(struct list_t)); ltmp->name = xstrdup(answer[2]); ltmp->next = NULL; if (llast) llast->next = ltmp; else lhead = ltmp; llast = ltmp; ret = upscli_list_next(&ups, numq, query, &numa, &answer); } if (!lhead) error_page("showcmds", "No instant commands supported", "This UPS doesn't support any instant commands."); do_header("Instant commands"); printf("
\n"); start_table(); /* include the description from checkhost() if present */ if (desc) printf("%s\n", desc); printf("\n"); printf("Instant commands\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); do_hidden("docmd"); printf("\n", monups); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
\n"); printf("\n"); do_pickups("showcmds"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } /* handle setting authentication data in the server */ static void send_auth(const char *next) { char buf[SMALLBUF]; snprintf(buf, sizeof(buf), "USERNAME %s\n", username); if (upscli_sendline(&ups, buf, strlen(buf)) < 0) { fprintf(stderr, "Can't set username: %s\n", upscli_strerror(&ups)); error_page(next, "Can't set username", "Set username failed: %s", upscli_strerror(&ups)); } if (upscli_readline(&ups, buf, sizeof(buf)) < 0) { /* test for old upsd that doesn't do USERNAME */ if (upscli_upserror(&ups) == UPSCLI_ERR_UNKCOMMAND) { error_page(next, "Protocol mismatch", "upsd version too old - USERNAME not supported"); } error_page(next, "Can't set user name", "Set user name failed: %s", upscli_strerror(&ups)); } snprintf(buf, sizeof(buf), "PASSWORD %s\n", password); if (upscli_sendline(&ups, buf, strlen(buf)) < 0) error_page(next, "Can't set password", "Password set failed: %s", upscli_strerror(&ups)); if (upscli_readline(&ups, buf, sizeof(buf)) < 0) error_page(next, "Can't set password", "Password set failed: %s", upscli_strerror(&ups)); } static void docmd(void) { char buf[SMALLBUF], *desc; if (!checkhost(monups, &desc)) error_page("showsettings", "Access denied", "Access to that host is not authorized"); /* the user is messing with us */ if (!upscommand) error_page("showcmds", "Form error", "No instant command selected"); /* (l)user took the default blank option */ if (strlen(upscommand) == 0) error_page("showcmds", "Form error", "No instant command selected"); upsd_connect(); send_auth("showcmds"); snprintf(buf, sizeof(buf), "INSTCMD %s %s\n", upsname, upscommand); if (upscli_sendline(&ups, buf, strlen(buf)) < 0) { do_header("Error while issuing command"); start_table(); printf("Error sending command: %s\n", upscli_strerror(&ups)); printf("\n"); do_pickups("showcmds"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } if (upscli_readline(&ups, buf, sizeof(buf)) < 0) { do_header("Error while reading command response"); start_table(); printf("Error reading command response: %s\n", upscli_strerror(&ups)); printf("\n"); do_pickups("showcmds"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } do_header("Issuing command"); start_table(); printf("
\n");
	printf("Sending command: %s\n", upscommand);
	printf("Response: %s\n", buf);
	printf("
\n"); printf("\n"); do_pickups("showcmds"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } static const char *get_data(const char *type, const char *varname) { int ret; unsigned int numq, numa; char **answer; const char *query[4]; query[0] = type; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_get(&ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) return NULL; /* */ return answer[3]; } static void do_string(const char *varname, int maxlen) { const char *val; val = get_data("VAR", varname); if (!val) { printf("Unavailable\n"); fprintf(stderr, "do_string: can't get current value of %s\n", varname); return; } printf("\n", varname, val, maxlen); } static void do_enum(const char *varname) { int ret; unsigned int numq, numa; char **answer, *val; const char *query[4], *tmp; /* get current value */ tmp = get_data("VAR", varname); if (!tmp) { printf("Unavailable\n"); fprintf(stderr, "do_enum: can't get current value of %s\n", varname); return; } /* tmp is a pointer into answer - have to save it somewhere else */ val = xstrdup(tmp); query[0] = "ENUM"; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_list_start(&ups, numq, query); if (ret < 0) { printf("Unavailable\n"); fprintf(stderr, "Error doing ENUM %s %s: %s\n", upsname, varname, upscli_strerror(&ups)); return; } ret = upscli_list_next(&ups, numq, query, &numa, &answer); printf("\n"); } static void do_type(const char *varname) { int ret; unsigned int i, numq, numa; char **answer; const char *query[4]; query[0] = "TYPE"; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_get(&ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) { printf("Unknown type\n"); return; } /* TYPE ... */ for (i = 3; i < numa; i++) { if (!strcasecmp(answer[i], "ENUM")) { do_enum(varname); return; } if (!strncasecmp(answer[i], "STRING:", 7)) { char *ptr, len; /* split out the : data */ ptr = strchr(answer[i], ':'); *ptr++ = '\0'; len = strtol(ptr, (char **) NULL, 10); do_string(varname, len); return; } /* ignore this one */ if (!strcasecmp(answer[i], "RW")) continue; printf("Unrecognized\n"); } } static void print_rw(const char *upsname, const char *varname) { const char *tmp; printf("\n"); printf(""); tmp = get_data("DESC", varname); if ((tmp) && (strcmp(tmp, "Unavailable") != 0)) printf("%s", tmp); else printf("%s", varname); printf("\n"); printf("\n"); do_type(varname); printf("\n"); printf("\n"); } static void showsettings(void) { int ret; unsigned int numq, numa; const char *query[2]; char **answer, *desc = NULL; struct list_t *lhead, *llast, *ltmp, *lnext; if (!checkhost(monups, &desc)) error_page("showsettings", "Access denied", "Access to that host is not authorized"); upsd_connect(); query[0] = "RW"; query[1] = upsname; numq = 2; ret = upscli_list_start(&ups, numq, query); if (ret < 0) { fprintf(stderr, "LIST RW %s failed: %s\n", upsname, upscli_strerror(&ups)); error_page("showsettings", "Server protocol error", "LIST RW command failed"); /* NOTREACHED */ } llast = lhead = NULL; ret = upscli_list_next(&ups, numq, query, &numa, &answer); while (ret == 1) { /* sock this entry away for later */ ltmp = xmalloc(sizeof(struct list_t)); ltmp->name = xstrdup(answer[2]); ltmp->next = NULL; if (llast) llast->next = ltmp; else lhead = ltmp; llast = ltmp; ret = upscli_list_next(&ups, numq, query, &numa, &answer); } do_header("Current settings"); printf("
\n"); start_table(); /* include the description from checkhost() if present */ if (desc) printf("%s\n", desc); printf("\n"); printf("Setting\n"); printf("Value\n"); /* use the list to get descriptions and types */ ltmp = lhead; while (ltmp) { lnext = ltmp->next; print_rw(upsname, ltmp->name); free(ltmp->name); free(ltmp); ltmp = lnext; } printf("\n"); printf("\n"); do_hidden("savesettings"); printf("\n", monups); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
\n"); printf("\n"); do_pickups("showsettings"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } static int setvar(const char *var, const char *val) { char buf[SMALLBUF], enc[SMALLBUF]; const char *tmp; /* get old value */ tmp = get_data("VAR", var); if (!tmp) { printf("Can't get old value for %s, aborting SET\n", var); return 0; } /* don't send a SET if it hasn't chnaged */ if (!strcmp(tmp, val)) return 0; printf("set %s to %s (was %s)\n", var, val, tmp); snprintf(buf, sizeof(buf), "SET VAR %s %s \"%s\"\n", upsname, var, pconf_encode(val, enc, sizeof(enc))); if (upscli_sendline(&ups, buf, strlen(buf)) < 0) { printf("Error: SET failed: %s\n", upscli_strerror(&ups)); return 0; } if (upscli_readline(&ups, buf, sizeof(buf)) < 0) { printf("Error: SET failed: %s\n", upscli_strerror(&ups)); return 0; } if (strncmp(buf, "OK", 2) != 0) { printf("Unexpected response: %s\n", buf); return 0; } printf("OK\n"); return 1; } /* turn a form submission of settings into SET commands for upsd */ static void savesettings(void) { int changed = 0; char *desc; uvtype_t *upsvar; if (!checkhost(monups, &desc)) error_page("showsettings", "Access denied", "Access to that host is not authorized"); upsd_connect(); upsvar = firstuv; send_auth("showsettings"); do_header("Saving settings"); start_table(); printf("
\n");

	while (upsvar) {
		changed += setvar(upsvar->var, upsvar->value);
		upsvar = upsvar->next;
	}

	if (changed == 0)
		printf("No settings changed.\n");
	else
		printf("Updated %d setting%s.\n",
			changed, changed == 1 ? "" : "s");

	printf("
\n"); printf("\n"); do_pickups("showsettings"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } static void initial_pickups(void) { do_header("Select a UPS"); start_table(); printf("\n"); do_pickups(""); printf("\n"); printf("\n"); printf("\n"); printf("\n"); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } static void upsset_conf_err(const char *errmsg) { upslogx(LOG_ERR, "Fatal error in parseconf(upsset.conf): %s", errmsg); } /* see if the user has confirmed their cgi directory's secure state */ static void check_conf(void) { char fn[SMALLBUF]; PCONF_CTX_t ctx; snprintf(fn, sizeof(fn), "%s/upsset.conf", confpath()); pconf_init(&ctx, upsset_conf_err); if (!pconf_file_begin(&ctx, fn)) { pconf_finish(&ctx); printf("
\n");
		printf("Error: Can't open upsset.conf to verify security settings.\n");
		printf("Refusing to start until this is fixed.\n");
		printf("
\n"); /* leave something in the httpd log for the admin */ fprintf(stderr, "upsset.conf does not exist to permit execution\n"); exit(EXIT_FAILURE); } while (pconf_file_next(&ctx)) { if (pconf_parse_error(&ctx)) { upslogx(LOG_ERR, "Parse error: %s:%d: %s", fn, ctx.linenum, ctx.errmsg); continue; } if (ctx.numargs < 1) continue; if (!strcmp(ctx.arglist[0], MAGIC_ENABLE_STRING)) magic_string_set = 1; } pconf_finish(&ctx); /* if we've been enabled, jump out of here and go to work */ if (magic_string_set == 1) return; printf("
\n");
	printf("Error: Secure mode has not been enabled in upsset.conf.\n");
	printf("Refusing to start until this is fixed.\n");
	printf("
\n"); /* leave something in the httpd log for the admin */ fprintf(stderr, "upsset.conf does not permit execution\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { username = password = function = monups = NULL; printf("Content-type: text/html\n\n"); /* see if the magic string is present in the config file */ check_conf(); /* see if there's anything waiting .. the server my not close STDIN properly */ if (1) { fd_set fds; struct timeval tv; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); tv.tv_sec = 0; tv.tv_usec = 250000; /* wait for up to 250ms for a POST response */ if ((select(STDIN_FILENO+1, &fds, 0, 0, &tv)) > 0) extractpostargs(); } if ((!username) || (!password) || (!function)) loginscreen(); if ((!strcmp(function, "pickups")) || (!monups)) initial_pickups(); if (!strcmp(function, "showsettings")) showsettings(); if (!strcmp(function, "savesettings")) savesettings(); #if 0 /* FUTURE */ if (!strcmp(function, "showstatus")) showstatus(); #endif if (!strcmp(function, "showcmds")) showcmds(); if (!strcmp(function, "docmd")) docmd(); printf("Error: Unhandled function name [%s]\n", function); return 0; } nut-2.7.2/clients/upslog.c0000644000175000017500000003004112301203176012360 00000000000000/* upslog - log ups values to a file for later collection and analysis Copyright (C) 1998 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Basic theory of operation: * * First we go through and parse as much of the status format string as * possible. We used to do this parsing run every time, but that's a * waste of CPU since it can't change during the program's run. * * This version does the parsing pass once, and creates a linked list of * pointers to the functions that do the work and the arg they get. * * That means the main loop just has to run the linked list and call * anything it finds in there. Everything happens from there, and we * don't have to pointlessly reparse the string every time around. */ #include "common.h" #include "nut_platform.h" #include "upsclient.h" #include "config.h" #include "timehead.h" #include "upslog.h" static int port, reopen_flag = 0, exit_flag = 0; static char *upsname, *hostname; static UPSCONN_t ups; static FILE *logfile; static const char *logfn, *monhost; static sigset_t nut_upslog_sigmask; static char logbuffer[LARGEBUF], *logformat; static flist_t *fhead = NULL; #define DEFAULT_LOGFORMAT "%TIME @Y@m@d @H@M@S% %VAR battery.charge% " \ "%VAR input.voltage% %VAR ups.load% [%VAR ups.status%] " \ "%VAR ups.temperature% %VAR input.frequency%" static void reopen_log(void) { if (logfile == stdout) { upslogx(LOG_INFO, "logging to stdout"); return; } fclose(logfile); logfile = fopen(logfn, "a"); if (logfile == NULL) fatal_with_errno(EXIT_FAILURE, "could not reopen logfile %s", logfn); } static void set_reopen_flag(int sig) { reopen_flag = sig; } static void set_exit_flag(int sig) { exit_flag = sig; } /* handlers: reload on HUP, exit on INT/QUIT/TERM */ static void setup_signals(void) { struct sigaction sa; sigemptyset(&nut_upslog_sigmask); sigaddset(&nut_upslog_sigmask, SIGHUP); sa.sa_mask = nut_upslog_sigmask; sa.sa_handler = set_reopen_flag; sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) < 0) fatal_with_errno(EXIT_FAILURE, "Can't install SIGHUP handler"); sa.sa_handler = set_exit_flag; if (sigaction(SIGINT, &sa, NULL) < 0) fatal_with_errno(EXIT_FAILURE, "Can't install SIGINT handler"); if (sigaction(SIGQUIT, &sa, NULL) < 0) fatal_with_errno(EXIT_FAILURE, "Can't install SIGQUIT handler"); if (sigaction(SIGTERM, &sa, NULL) < 0) fatal_with_errno(EXIT_FAILURE, "Can't install SIGTERM handler"); } static void help(const char *prog) { printf("UPS status logger.\n"); printf("\nusage: %s [OPTIONS]\n", prog); printf("\n"); printf(" -f - Log format. See below for details.\n"); printf(" - Use -f \"\" so your shell doesn't break it up.\n"); printf(" -i - Time between updates, in seconds\n"); printf(" -l - Log file name, or - for stdout\n"); printf(" -p - Base name for PID file (defaults to \"%s\")\n", prog); printf(" -s - Monitor UPS - @[:]\n"); printf(" - Example: -s myups@server\n"); printf(" -u - Switch to if started as root\n"); printf("\n"); printf("Some valid format string escapes:\n"); printf("\t%%%% insert a single %%\n"); printf("\t%%TIME format%% insert the time with strftime formatting\n"); printf("\t%%HOST%% insert the local hostname\n"); printf("\t%%UPSHOST%% insert the host of the ups being monitored\n"); printf("\t%%PID%% insert the pid of upslog\n"); printf("\t%%VAR varname%% insert the value of ups variable varname\n\n"); printf("format string defaults to:\n"); printf("%s\n", DEFAULT_LOGFORMAT); printf("\n"); printf("See the upslog(8) man page for more information.\n"); exit(EXIT_SUCCESS); } /* print current host name */ static void do_host(const char *arg) { int ret; char hn[LARGEBUF]; ret = gethostname(hn, sizeof(hn)); if (ret != 0) { upslog_with_errno(LOG_ERR, "gethostname failed"); return; } snprintfcat(logbuffer, sizeof(logbuffer), "%s", hn); } static void do_upshost(const char *arg) { snprintfcat(logbuffer, sizeof(logbuffer), "%s", monhost); } static void do_pid(const char *arg) { snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (long)getpid()); } static void do_time(const char *arg) { unsigned int i; char timebuf[SMALLBUF], *format; time_t tod; format = xstrdup(arg); /* @s are used on the command line since % is taken */ for (i = 0; i < strlen(format); i++) if (format[i] == '@') format[i] = '%'; time(&tod); strftime(timebuf, sizeof(timebuf), format, localtime(&tod)); snprintfcat(logbuffer, sizeof(logbuffer), "%s", timebuf); free(format); } static void getvar(const char *var) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; query[0] = "VAR"; query[1] = upsname; query[2] = var; numq = 3; ret = upscli_get(&ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) { snprintfcat(logbuffer, sizeof(logbuffer), "NA"); return; } snprintfcat(logbuffer, sizeof(logbuffer), "%s", answer[3]); } static void do_var(const char *arg) { if ((!arg) || (strlen(arg) < 1)) { snprintfcat(logbuffer, sizeof(logbuffer), "INVALID"); return; } /* old variable names are no longer supported */ if (!strchr(arg, '.')) { snprintfcat(logbuffer, sizeof(logbuffer), "INVALID"); return; } /* a UPS name is now required */ if (!upsname) { snprintfcat(logbuffer, sizeof(logbuffer), "INVALID"); return; } getvar(arg); } static void do_etime(const char *arg) { time_t tod; time(&tod); snprintfcat(logbuffer, sizeof(logbuffer), "%ld", (unsigned long) tod); } static void print_literal(const char *arg) { snprintfcat(logbuffer, sizeof(logbuffer), "%s", arg); } /* register another parsing function to be called later */ static void add_call(void (*fptr)(const char *arg), const char *arg) { flist_t *tmp, *last; tmp = last = fhead; while (tmp) { last = tmp; tmp = tmp->next; } tmp = xmalloc(sizeof(flist_t)); tmp->fptr = fptr; if (arg) tmp->arg = xstrdup(arg); else tmp->arg = NULL; tmp->next = NULL; if (last) last->next = tmp; else fhead = tmp; } /* turn the format string into a list of function calls with args */ static void compile_format(void) { unsigned int i; int j, found, ofs; char *cmd, *arg, *ptr; for (i = 0; i < strlen(logformat); i++) { /* if not a % sequence, append character and start over */ if (logformat[i] != '%') { char buf[4]; /* we have to stuff it into a string first */ snprintf(buf, sizeof(buf), "%c", logformat[i]); add_call(print_literal, buf); continue; } /* if a %%, append % and start over */ if (logformat[i+1] == '%') { add_call(print_literal, "%"); /* make sure we don't parse the second % next time */ i++; continue; } /* it must start with a % now - %[ ]%*/ cmd = xstrdup(&logformat[i+1]); ptr = strchr(cmd, '%'); /* no trailing % = broken */ if (!ptr) { add_call(print_literal, "INVALID"); free(cmd); continue; } *ptr = '\0'; /* remember length (plus first %) so we can skip over it */ ofs = strlen(cmd) + 1; /* jump out to argument (if any) */ arg = strchr(cmd, ' '); if (arg) *arg++ = '\0'; found = 0; /* see if we know how to handle this command */ for (j = 0; logcmds[j].name != NULL; j++) { if (strncasecmp(cmd, logcmds[j].name, strlen(logcmds[j].name)) == 0) { add_call(logcmds[j].func, arg); found = 1; break; } } free(cmd); if (!found) add_call(print_literal, "INVALID"); /* now do the skip ahead saved from before */ i += ofs; } /* for (i = 0; i < strlen(logformat); i++) */ } /* go through the list of functions and call them in order */ static void run_flist(void) { flist_t *tmp; tmp = fhead; memset(logbuffer, 0, sizeof(logbuffer)); while (tmp) { tmp->fptr(tmp->arg); tmp = tmp->next; } fprintf(logfile, "%s\n", logbuffer); fflush(logfile); } /* -s * -l * -i * -f * -u */ int main(int argc, char **argv) { int interval = 30, i; const char *prog = xbasename(argv[0]); time_t now, nextpoll = 0; const char *user = NULL; struct passwd *new_uid = NULL; const char *pidfilebase = prog; logformat = DEFAULT_LOGFORMAT; user = RUN_AS_USER; printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:")) != -1) { switch(i) { case 'h': help(prog); break; case 's': monhost = optarg; break; case 'l': logfn = optarg; break; case 'i': interval = atoi(optarg); break; case 'f': logformat = optarg; break; case 'u': user = optarg; break; case 'V': exit(EXIT_SUCCESS); case 'p': pidfilebase = optarg; break; } } argc -= optind; argv += optind; /* not enough args for the old way? */ if ((argc == 1) || (argc == 2)) help(prog); /* see if it's being called in the old style - 3 or 4 args */ /* [] */ if (argc >= 3) { monhost = argv[0]; logfn = argv[1]; interval = atoi(argv[2]); } if (argc >= 4) { /* read out the remaining argv entries to the format string */ logformat = xmalloc(LARGEBUF); memset(logformat, '\0', LARGEBUF); for (i = 3; i < argc; i++) snprintfcat(logformat, LARGEBUF, "%s ", argv[i]); } if (!monhost) fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s "); if (!logfn) fatalx(EXIT_FAILURE, "No filename defined for logging - use -l "); /* shouldn't happen */ if (!logformat) fatalx(EXIT_FAILURE, "No format defined - but this should be impossible"); printf("logging status of %s to %s (%is intervals)\n", monhost, logfn, interval); if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n"); } if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) fprintf(stderr, "Warning: initial connect failed: %s\n", upscli_strerror(&ups)); if (strcmp(logfn, "-") == 0) logfile = stdout; else logfile = fopen(logfn, "a"); if (logfile == NULL) fatal_with_errno(EXIT_FAILURE, "could not open logfile %s", logfn); /* now drop root if we have it */ new_uid = get_user_pwent(user); open_syslog(prog); if (logfile != stdout) background(); setup_signals(); writepid(pidfilebase); become_user(new_uid); compile_format(); while (exit_flag == 0) { time(&now); if (nextpoll > now) { /* there is still time left, so sleep it off */ sleep(difftime(nextpoll, now)); nextpoll += interval; } else { /* we spent more time in polling than the interval allows */ nextpoll = now + interval; } if (reopen_flag) { upslogx(LOG_INFO, "Signal %d: reopening log file", reopen_flag); reopen_log(); reopen_flag = 0; } /* reconnect if necessary */ if (upscli_fd(&ups) < 0) { upscli_connect(&ups, hostname, port, 0); } run_flist(); /* don't keep connection open if we don't intend to use it shortly */ if (interval > 30) { upscli_disconnect(&ups); } } upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); if (logfile != stdout) fclose(logfile); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } /* Formal do_upsconf_args implementation to satisfy linker on AIX */ #if (defined NUT_PLATFORM_AIX) void do_upsconf_args(char *upsname, char *var, char *val) { fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called"); } #endif /* end of #if (defined NUT_PLATFORM_AIX) */ nut-2.7.2/clients/upsimage.c0000644000175000017500000004620412277355125012707 00000000000000/* upsimage - cgi program to create graphical ups information reports Status: 20020814 - Simon Rozman - redesigned the meters 20020823 - Simon Rozman - added support for width, height and scale_height parameters - added support for outvolt - noimage now writes out a clue, why upsimage failed 20020902 - Simon Rozman - background now transparent by default - added support for colorization parameters - removed linear antialiasing of the scale, until I come up with a better algorithm 20020913 - Simon Rozman - added width, height and scale_height to imgarg table 20020928 - Simon Rozman - added imgvar table to hold description, how to draw each UPS variable supported - added support for ACFREQ, OUT_FREQ and UPSTEMP Copyrights: (C) 1998 Russell Kroll (C) 2002 Simon Rozman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "upsclient.h" #include "cgilib.h" #include #include #include #include "upsimagearg.h" #define MAX_CGI_STRLEN 64 static char *monhost = NULL, *cmd = NULL; static int port; static char *upsname, *hostname; static UPSCONN_t ups; #define RED(x) ((x >> 16) & 0xff) #define GREEN(x) ((x >> 8) & 0xff) #define BLUE(x) (x & 0xff) void parsearg(char *var, char *value) { int i, v; /* avoid bogus junk from evil people */ if ((strlen(var) > MAX_CGI_STRLEN) || (strlen(value) > MAX_CGI_STRLEN)) return; if (!strcmp(var, "host")) { free(monhost); monhost = xstrdup(value); return; } if (!strcmp(var, "display")) { free(cmd); cmd = xstrdup(value); return; } /* see if this is one of the shared (upsimagearg.h) variables */ for (i = 0; imgarg[i].name != NULL; i++) { if (!strcmp(imgarg[i].name, var)) { if (!strncmp(value, "0x", 2)) v = strtoul(value + 2, (char **)NULL, 16); else v = atoi(value); /* avoid false numbers from bad people */ if (v < imgarg[i].min) imgarg[i].val = imgarg[i].min; else if (v > imgarg[i].max) imgarg[i].val = imgarg[i].max; else imgarg[i].val = v; return; } } } /* return the value from the URL or the default if it wasn't set */ static int get_imgarg(const char *name) { int i; for (i = 0; imgarg[i].name != NULL; i++) if (!strcmp(imgarg[i].name, name)) return imgarg[i].val; return -1; } /* write the HTML header then have gd dump the image */ static void drawimage(gdImagePtr im) { printf("Pragma: no-cache\n"); printf("Content-type: image/png\n\n"); gdImagePng(im, stdout); gdImageDestroy(im); upscli_disconnect(&ups); exit(EXIT_SUCCESS); } /* helper function to allocate color in the image */ static int color_alloc(gdImagePtr im, int rgb) { return gdImageColorAllocate(im, RED(rgb), GREEN(rgb), BLUE(rgb)); } /* draws the scale behind the bar indicator */ static void drawscale( gdImagePtr im, /* image where we would like to draw scale */ int lvllo, int lvlhi, /* min and max numbers on the scale */ int step, int step5, int step10, /* steps for minor, submajor and major dashes */ int redlo1, int redhi1, /* first red zone start and end */ int redlo2, int redhi2, /* second red zone start and end */ int grnlo, int grnhi) /* green zone start and end */ { int col1, col2, back_color, scale_num_color, ok_zone_maj_color, ok_zone_min_color, neutral_zone_maj_color, neutral_zone_min_color, warn_zone_maj_color, warn_zone_min_color; char lbltxt[SMALLBUF]; int y, level, range; int width, height, scale_height; back_color = color_alloc(im, get_imgarg("back_col")); scale_num_color = color_alloc(im, get_imgarg("scale_num_col")); ok_zone_maj_color = color_alloc(im, get_imgarg("ok_zone_maj_col")); ok_zone_min_color = color_alloc(im, get_imgarg("ok_zone_min_col")); neutral_zone_maj_color = color_alloc(im, get_imgarg("neutral_zone_maj_col")); neutral_zone_min_color = color_alloc(im, get_imgarg("neutral_zone_min_col")); warn_zone_maj_color = color_alloc(im, get_imgarg("warn_zone_maj_col")); warn_zone_min_color = color_alloc(im, get_imgarg("warn_zone_min_col")); width = get_imgarg("width"); height = get_imgarg("height"); scale_height = get_imgarg("scale_height"); /* start out with a background color and make it transparent */ gdImageFilledRectangle(im, 0, 0, width, height, back_color); gdImageColorTransparent(im, back_color); range = lvlhi - lvllo; /* draw scale to correspond with the values */ for (level = lvlhi; level >= lvllo; level -= step) { /* select dash RGB color according to the level */ if (((redlo1 <= level) && (level <=redhi1)) || ((redlo2 <= level) && (level <=redhi2))) { col1 = warn_zone_maj_color; col2 = warn_zone_min_color; } else if ((grnlo <= level) && (level <= grnhi)) { col1 = ok_zone_maj_color; col2 = ok_zone_min_color; } else { col1 = neutral_zone_maj_color; col2 = neutral_zone_min_color; } /* calculate integer value for y */ y = scale_height * (lvlhi - level) / range; /* draw major, semimajor or minor dash accordingly */ if (level % step10 == 0) { gdImageLine(im, 0, y, width, y, col1); } else { if (level % step5 == 0) gdImageLine(im, 5, y, width - 5, y, col2); else gdImageLine(im, 10, y, width - 10, y, col2); } } /* put the values on the scale */ for (level = lvlhi; level >= lvllo; level -= step) { if (level % step10 == 0) { y = scale_height * (lvlhi - level) / range; snprintf(lbltxt, sizeof(lbltxt), "%d", level); gdImageString(im, gdFontMediumBold, width - strlen(lbltxt)*gdFontMediumBold->w, y, (unsigned char *) lbltxt, scale_num_color); } } } /* draws the bar style indicator */ static void drawbar( int lvllo, int lvlhi, /* min and max numbers on the scale */ int step, int step5, int step10, /* steps for minor, submajor and major dashes */ int redlo1, int redhi1, /* first red zone start and end */ int redlo2, int redhi2, /* second red zone start and end */ int grnlo, int grnhi, /* green zone start and end */ double value, /* UPS variable value to draw */ const char *format /* printf style format to be used when rendering summary text */ ) { gdImagePtr im; int bar_color, summary_color; char text[SMALLBUF]; int bar_y; int width, height, scale_height; /* get the dimension parameters */ width = get_imgarg("width"); height = get_imgarg("height"); scale_height = get_imgarg("scale_height"); /* create the image */ im = gdImageCreate(width, height); /* draw the scale */ drawscale(im, lvllo, lvlhi, step, step5, step10, redlo1, redhi1, redlo2, redhi2, grnlo, grnhi); /* allocate colors for the bar and summary text */ bar_color = color_alloc(im, get_imgarg("bar_col")); summary_color = color_alloc(im, get_imgarg("summary_col")); /* rescale UPS value to fit in the scale */ bar_y = (1 - (value - lvllo) / (lvlhi - lvllo)) * scale_height; /* sanity checks: */ /* 1: if value is above maximum, then bar_y goes negative */ if (bar_y < 0) bar_y = 0; /* 2: if value is below minimum, bar_y goes off the scale */ if (bar_y > scale_height) bar_y = scale_height; /* draw it */ gdImageFilledRectangle(im, 25, bar_y, width - 25, scale_height, bar_color); /* stick the text version of the value at the bottom center */ snprintf(text, sizeof(text), format, value); gdImageString(im, gdFontMediumBold, (width - strlen(text)*gdFontMediumBold->w)/2, height - gdFontMediumBold->h, (unsigned char *) text, summary_color); drawimage(im); /* NOTREACHED */ } /* draws the error image */ static void noimage(const char *fmt, ...) { gdImagePtr im; int back_color, summary_color; int width, height; char msg[SMALLBUF]; va_list ap; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); width = get_imgarg("width"); height = get_imgarg("height"); im = gdImageCreate(width, height); back_color = color_alloc(im, get_imgarg("back_col")); summary_color = color_alloc(im, get_imgarg("summary_col")); gdImageFilledRectangle(im, 0, 0, width, height, back_color); gdImageColorTransparent(im, back_color); if (width > height) gdImageString(im, gdFontMediumBold, (width - strlen(msg)*gdFontMediumBold->w)/2, (height - gdFontMediumBold->h)/2, (unsigned char *) msg, summary_color); else gdImageStringUp(im, gdFontMediumBold, (width - gdFontMediumBold->h)/2, (height + strlen(msg)*gdFontMediumBold->w)/2, (unsigned char *) msg, summary_color); drawimage(im); /* NOTREACHED */ } /* draws bar indicator when minimum, nominal or maximum values for the given UPS variable can be determined. deviation < 0 means that values below nom should be grey instead of green */ static void drawgeneralbar(double var, int min, int nom, int max, int deviation, const char *format) { int hi, lo, step1, step5, step10, graybelownom=0; if(deviation < 0) { deviation=-deviation; graybelownom=1; } if ((nom == -1) && ((min == -1) || (max == -1))) noimage("Can't determine range"); /* if min, max and nom are mixed up, arrange them appropriately */ if (nom != -1) { if (min == -1) min = nom - 3*deviation; if (max == -1) max = nom + 3*deviation; } else { /* if nominal value isn't available, assume, it's the average between min and max */ nom = (min + max) / 2; } /* draw scale in the background */ if ((max - min) <= 50) { /* the scale is sparse enough to draw finer scale */ step1 = 1; step5 = 5; step10 = 10; } else if((max - min) <= 100) { step1 = 2; step5 = 10; step10 = 20; } else { step1 = 5; step5 = 20; step10 = 40; } /* round min and max points to get high and low numbers for graph */ lo = ((min - deviation) / step10) * step10; hi = ((max + deviation + step10/2) / step10) * step10; if(!graybelownom) { drawbar(lo, hi, step1, step5, step10, max, hi, lo, min, nom - deviation, nom + deviation, var, format); } else { drawbar(lo, hi, step1, step5, step10, 0, min, max, hi, nom, max, var, format); } /* NOTREACHED */ } /* draws input and output voltage bar style indicators */ static void draw_utility(double var, int min, int nom, int max, int deviation, const char *format) { /* hack: deal with hardware that doesn't have known transfer points */ if (min == -1) { if(var < 200) { min = 90; } else if(var < 300) { min = 200; } else { min = 340; } } /* somewhere between 220 and 230 V, to keep everybody satisfied */ if (nom == -1) { if(var < 200) { nom = 110; } else if(var < 300) { nom = 225; } else { nom = 400; } } /* symmetrical around nom */ if (max == -1) max = nom+(nom-min); /* Acceptable range of voltage is 85%-110% of nominal voltage * in EU at least. Be conservative and say +-10% */ deviation = nom*0.1; drawgeneralbar(var, min, nom, max, deviation, format); /* NOTREACHED */ } /* draws battery.percent bar style indicator */ static void draw_battpct(double var, int min, int nom, int max, int deviation, const char *format) { if (min < 0) { min = 50; } drawbar(0, 100, 2, 10, 20, 0, min, -1, -1, 80, 100, var, format); } /* draws battery.voltage bar style indicator */ static void draw_battvolt(double var, int min, int nom, int max, int deviation, const char *format) { if(nom == -1) { /* Use a fixed set of reasonable nominal voltages, seems to * be the only way to get reasonable behaviour during * discharge */ if(var < 9) nom = 6; else if(var < 18) nom = 12; else if(var < 30) nom = 24; else if(var < 60) nom = 48; else if(var < 120) nom = 96; else if(var < 230) nom = 192; else nom = 384; } if(min == -1) { min = nom/2*1.6+1; /* Assume a 2V cell is dead at 1.6V */ } if(max == -1) { max = nom/2*2.3+1; /* Assume 2.3V float charge voltage */ } if (nom < min || nom > max) nom = -1; deviation = -(nom*0.05); /* 5% deviation from nominal voltage */ if(deviation==0) { deviation = -1; } drawgeneralbar(var, min, nom, max, deviation, format); } /* draws ups.load bar style indicator */ static void draw_upsload(double var, int min, int nom, int max, int deviation, const char *format) { drawbar(0, 125, 5, 5, 25, 100, 125, -1, -1, 0, 50, var, format); } /* draws temperature bar style indicator */ static void draw_temperature(double var, int min, int nom, int max, int deviation, const char *format) { int hi = get_imgarg("tempmax"); int lo = get_imgarg("tempmin"); drawbar(lo, hi, 1, 5, 10, lo, min, max, hi, -1, -1, var, format); } /* draws humidity bar style indicator */ static void draw_humidity(double var, int min, int nom, int max, int deviation, const char *format) { drawbar(0, 100, 2, 10, 20, 0, min, max, 100, -1, -1, var, format); } static int get_var(const char *var, char *buf, size_t buflen) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; query[0] = "VAR"; query[1] = upsname; query[2] = var; numq = 3; ret = upscli_get(&ups, numq, query, &numa, &answer); if (ret < 0) return 0; if (numa < numq) return 0; snprintf(buf, buflen, "%s", answer[3]); return 1; } int main(int argc, char **argv) { char str[SMALLBUF]; int i, min, nom, max; double var = 0; extractcgiargs(); /* no 'host=' or 'display=' given */ if ((!monhost) || (!cmd)) noimage("No host or display"); if (!checkhost(monhost, NULL)) noimage("Access denied"); upsname = hostname = NULL; if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) { noimage("Invalid UPS definition (upsname[@hostname[:port]])\n"); exit(EXIT_FAILURE); } if (upscli_connect(&ups, hostname, port, 0) < 0) { noimage("Can't connect to server:\n%s\n", upscli_strerror(&ups)); exit(EXIT_FAILURE); } for (i = 0; imgvar[i].name; i++) if (!strcmp(cmd, imgvar[i].name)) { /* sanity check whether we have draw function registered with this variable */ if (!imgvar[i].drawfunc) { noimage("Draw function N/A"); exit(EXIT_FAILURE); } /* get the variable value */ if (get_var(imgvar[i].name, str, sizeof(str)) == 1) { var = strtod(str, NULL); } else { /* no value, no fun */ snprintf(str, sizeof(str), "%s N/A", imgvar[i].name); noimage(str); exit(EXIT_FAILURE); } /* when getting minimum, nominal and maximum values, we first look if the marginal value is supported by the UPS driver, if not, we look it up in the imgarg table under the SAME name */ /* get the minimum value */ if (imgvar[i].minimum) { if (get_var(imgvar[i].minimum, str, sizeof(str)) == 1) { min = atoi(str); } else { min = get_imgarg(imgvar[i].minimum); } } else { min = -1; } /* get the nominal value */ if (imgvar[i].nominal) { if (get_var(imgvar[i].nominal, str, sizeof(str)) == 1) { nom = atoi(str); } else { nom = get_imgarg(imgvar[i].nominal); } } else { nom = -1; } /* get the maximum value */ if (imgvar[i].maximum) { if (get_var(imgvar[i].maximum, str, sizeof(str)) == 1) { max = atoi(str); } else { max = get_imgarg(imgvar[i].maximum); } } else { max = -1; } imgvar[i].drawfunc(var, min, nom, max, imgvar[i].deviation, imgvar[i].format); exit(EXIT_SUCCESS); } noimage("Unknown display"); exit(EXIT_FAILURE); } imgvar_t imgvar[] = { { "input.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "input.L1-N.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "input.L2-N.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "input.L3-N.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "input.L1-L2.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "input.L2-L3.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "input.L3-L1.voltage", "input.transfer.low", "input.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "battery.charge", "battery.charge.low", NULL, NULL, 0, "%.1f %%", draw_battpct }, { "battery.voltage", "battery.voltage.low", "battery.voltage.nominal", "battery.voltage.high", 0, "%.1f VDC", draw_battvolt }, /* We use 'high' ASCII for the degrees symbol, since the gdImageString() * function doesn't understand UTF-8 or HTML escape sequences. :-( */ { "ups.temperature", "ups.temperature.low", NULL, "ups.temperature.high", 0, "%.1f \260C", draw_temperature }, /* Same here. */ { "ambient.temperature", "ambient.temperature.low", NULL, "ambient.temperature.high", 0, "%.1f \260C", draw_temperature }, { "ambient.humidity", "ambient.humidity.low", NULL, "ambient.humidity.high", 0, "%.1f %%", draw_humidity }, { "input.frequency", NULL, "input.frequency.nominal", NULL, 2, "%.1f Hz", drawgeneralbar }, { "ups.load", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.L1.power.percent", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.L2.power.percent", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.L3.power.percent", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.L1.realpower.percent", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.L2.realpower.percent", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.L3.realpower.percent", NULL, NULL, NULL, 0, "%.1f %%", draw_upsload }, { "output.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.L1-N.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.L2-N.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.L3-N.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.L1-L2.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.L2-L3.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.L3-L1.voltage", "input.transfer.low", "output.voltage.nominal", "input.transfer.high", 0, "%.1f VAC", draw_utility }, { "output.frequency", NULL, "output.frequency.nominal", NULL, 2, "%.1f Hz", drawgeneralbar }, { NULL, NULL, NULL, NULL, 0, NULL, NULL } }; nut-2.7.2/clients/upssched.h0000644000175000017500000000062412301203176012676 00000000000000/* upssched.h - supporting structures */ #include #define SERIALIZE_INIT 1 #define SERIALIZE_SET 2 #define SERIALIZE_WAIT 3 #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* track client connections */ typedef struct conn_s { int fd; PCONF_CTX_t ctx; struct conn_s *next; } conn_t; #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/upsimagearg.h0000644000175000017500000000530112277355125013377 00000000000000/* upsimagearg.h - arguments passed between upsstats and upsimage Copyright (C) 2002 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif struct { char *name; int val; /* hex digits, ala HTML */ int min; /* minimum reasonable value */ int max; /* maximum reasonable value */ } imgarg[] = { { "width", 100, 50, 200 }, { "height", 350, 100, 500 }, { "scale_height", 300, 100, 500 }, { "back_col", 0x000000, 0x000000, 0xffffff }, { "scale_num_col", 0xffff00, 0x000000, 0xffffff }, { "summary_col", 0xffff00, 0x000000, 0xffffff }, { "ok_zone_maj_col", 0x00ff00, 0x000000, 0xffffff }, { "ok_zone_min_col", 0x007800, 0x000000, 0xffffff }, { "neutral_zone_maj_col", 0xffffff, 0x000000, 0xffffff }, { "neutral_zone_min_col", 0x646464, 0x000000, 0xffffff }, { "warn_zone_maj_col", 0xff0000, 0x000000, 0xffffff }, { "warn_zone_min_col", 0x960000, 0x000000, 0xffffff }, { "bar_col", 0x00ff00, 0x000000, 0xffffff }, { "tempmin", 0, -100, 150 }, { "tempmax", 40, -100, 150 }, { "nom_in_freq", 50, 0, 100 }, { "nom_out_freq", 50, 0, 100 }, { NULL, 0, 0, 0 } }; typedef struct { char *name; /* name of the UPS variable */ char *minimum; /* name of minimum value UPS variable or variable in imgarg table */ char *nominal; /* as above, only for nominal value */ char *maximum; /* as above, only for maximum value */ int deviation; /* variable deviation - width of green zone */ char *format; /* format string to generate summary text */ /* pointer to drawing function */ void (*drawfunc)(double, int, int, int, int, const char*); } imgvar_t; extern imgvar_t imgvar[]; #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/cgilib.c0000644000175000017500000001005412277355125012320 00000000000000/* cgilib - common routines for CGI programs Copyright (C) 1999 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "common.h" #include "cgilib.h" #include "parseconf.h" static char *unescape(char *buf) { size_t i, buflen; char ch, *newbuf, hex[8]; buflen = strlen(buf) + 2; newbuf = xmalloc(buflen); *newbuf = '\0'; fflush(stdout); for (i = 0; i < buflen - 1; i++) { ch = buf[i]; if (ch == '+') ch = ' '; if (ch == '%') { if (i + 2 > buflen) fatalx(EXIT_FAILURE, "string too short for escaped char"); hex[0] = buf[++i]; hex[1] = buf[++i]; hex[2] = '\0'; if (!isxdigit((unsigned char) hex[0]) || !isxdigit((unsigned char) hex[0])) fatalx(EXIT_FAILURE, "bad escape char"); ch = strtol(hex, NULL, 16); if ((ch == 10) || (ch == 13)) ch = ' '; } snprintfcat(newbuf, buflen, "%c", ch); } return newbuf; } void extractcgiargs(void) { char *query, *ptr, *eq, *varname, *value, *amp; char *cleanval, *cleanvar; query = getenv("QUERY_STRING"); if (query == NULL) return; /* not run as a cgi script! */ if (strlen(query) == 0) return; /* no query string to parse! */ /* varname=value&varname=value&varname=value ... */ ptr = query; while (ptr) { varname = ptr; eq = strchr(varname, '='); if (!eq) { ptr = strchr(varname, '&'); if (ptr) *ptr++ = '\0'; cleanvar = unescape(varname); parsearg(cleanvar, ""); free(cleanvar); continue; } *eq = '\0'; value = eq + 1; amp = strchr(value, '&'); if (amp) { ptr = amp + 1; *amp = '\0'; } else ptr = NULL; cleanvar = unescape(varname); cleanval = unescape(value); parsearg(cleanvar, cleanval); free(cleanvar); free(cleanval); } } void extractpostargs(void) { char buf[SMALLBUF], *ptr, *cleanval; int ch; ch = fgetc(stdin); buf[0] = '\0'; while (ch != EOF) { if (ch == '&') { ptr = strchr(buf, '='); if (!ptr) parsearg(buf, ""); else { *ptr++ = '\0'; cleanval = unescape(ptr); parsearg(buf, cleanval); free(cleanval); } buf[0] = '\0'; } else snprintfcat(buf, sizeof(buf), "%c", ch); ch = fgetc(stdin); } if (strlen(buf) != 0) { ptr = strchr(buf, '='); if (!ptr) parsearg(buf, ""); else { *ptr++ = '\0'; cleanval = unescape(ptr); parsearg(buf, cleanval); free(cleanval); } } } /* called for fatal errors in parseconf like malloc failures */ static void cgilib_err(const char *errmsg) { upslogx(LOG_ERR, "Fatal error in parseconf(ups.conf): %s", errmsg); } int checkhost(const char *host, char **desc) { char fn[SMALLBUF]; PCONF_CTX_t ctx; if (!host) return 0; /* deny null hostnames */ snprintf(fn, sizeof(fn), "%s/hosts.conf", confpath()); pconf_init(&ctx, cgilib_err); if (!pconf_file_begin(&ctx, fn)) { pconf_finish(&ctx); fprintf(stderr, "%s\n", ctx.errmsg); return 0; /* failed: deny access */ } while (pconf_file_next(&ctx)) { if (pconf_parse_error(&ctx)) { fprintf(stderr, "Error: %s:%d: %s\n", fn, ctx.linenum, ctx.errmsg); continue; } /* MONITOR */ if (ctx.numargs < 3) continue; if (strcmp(ctx.arglist[0], "MONITOR") != 0) continue; if (!strcmp(ctx.arglist[1], host)) { if (desc) *desc = xstrdup(ctx.arglist[2]); pconf_finish(&ctx); return 1; /* found: allow access */ } } pconf_finish(&ctx); return 0; /* not found: access denied */ } nut-2.7.2/clients/upsstats.h0000644000175000017500000000177612277355125012775 00000000000000/* upsstats.h - structures for upsstats Copyright (C) 2002 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif typedef struct { char *sys; char *desc; void *next; } ulist_t; #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/Makefile.in0000644000175000017500000011342412324034367012770 00000000000000# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Network UPS Tools: clients VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @WITH_SSL_TRUE@am__append_1 = $(LIBSSL_LIBS) @WITH_SSL_TRUE@am__append_2 = $(LIBSSL_CFLAGS) @WITH_CGI_TRUE@am__append_3 = $(LIBGD_CFLAGS) bin_PROGRAMS = upsc$(EXEEXT) upslog$(EXEEXT) upsrw$(EXEEXT) \ upscmd$(EXEEXT) sbin_PROGRAMS = upsmon$(EXEEXT) upssched$(EXEEXT) @WITH_CGI_TRUE@cgiexec_PROGRAMS = upsstats.cgi$(EXEEXT) \ @WITH_CGI_TRUE@ upsimage.cgi$(EXEEXT) upsset.cgi$(EXEEXT) @WITH_SSL_TRUE@am__append_4 = $(LIBSSL_LIBS) subdir = clients DIST_COMMON = $(am__include_HEADERS_DIST) $(dist_bin_SCRIPTS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nut_arg_with.m4 \ $(top_srcdir)/m4/nut_check_asciidoc.m4 \ $(top_srcdir)/m4/nut_check_libavahi.m4 \ $(top_srcdir)/m4/nut_check_libfreeipmi.m4 \ $(top_srcdir)/m4/nut_check_libgd.m4 \ $(top_srcdir)/m4/nut_check_libltdl.m4 \ $(top_srcdir)/m4/nut_check_libneon.m4 \ $(top_srcdir)/m4/nut_check_libnetsnmp.m4 \ $(top_srcdir)/m4/nut_check_libnss.m4 \ $(top_srcdir)/m4/nut_check_libopenssl.m4 \ $(top_srcdir)/m4/nut_check_libpowerman.m4 \ $(top_srcdir)/m4/nut_check_libusb.m4 \ $(top_srcdir)/m4/nut_check_libwrap.m4 \ $(top_srcdir)/m4/nut_check_os.m4 \ $(top_srcdir)/m4/nut_report_feature.m4 \ $(top_srcdir)/m4/nut_type_socklen_t.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libnutclient_la_LIBADD = am_libnutclient_la_OBJECTS = nutclient.lo libnutclient_la_OBJECTS = $(am_libnutclient_la_OBJECTS) libnutclient_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libnutclient_la_LDFLAGS) $(LDFLAGS) -o $@ am__DEPENDENCIES_1 = @WITH_SSL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) libupsclient_la_DEPENDENCIES = ../common/libcommonclient.la \ $(am__DEPENDENCIES_2) am_libupsclient_la_OBJECTS = upsclient.lo libupsclient_la_OBJECTS = $(am_libupsclient_la_OBJECTS) libupsclient_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libupsclient_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(cgiexec_PROGRAMS) $(sbin_PROGRAMS) am_upsc_OBJECTS = upsc.$(OBJEXT) upsc_OBJECTS = $(am_upsc_OBJECTS) upsc_LDADD = $(LDADD) upsc_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_upscmd_OBJECTS = upscmd.$(OBJEXT) upscmd_OBJECTS = $(am_upscmd_OBJECTS) upscmd_LDADD = $(LDADD) upscmd_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_upsimage_cgi_OBJECTS = upsimage.$(OBJEXT) cgilib.$(OBJEXT) upsimage_cgi_OBJECTS = $(am_upsimage_cgi_OBJECTS) am__DEPENDENCIES_3 = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) upsimage_cgi_DEPENDENCIES = $(am__DEPENDENCIES_3) \ $(am__DEPENDENCIES_1) am_upslog_OBJECTS = upslog.$(OBJEXT) upslog_OBJECTS = $(am_upslog_OBJECTS) upslog_LDADD = $(LDADD) upslog_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_upsmon_OBJECTS = upsmon.$(OBJEXT) upsmon_OBJECTS = $(am_upsmon_OBJECTS) upsmon_LDADD = $(LDADD) upsmon_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_upsrw_OBJECTS = upsrw.$(OBJEXT) upsrw_OBJECTS = $(am_upsrw_OBJECTS) upsrw_LDADD = $(LDADD) upsrw_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_upssched_OBJECTS = upssched.$(OBJEXT) upssched_OBJECTS = $(am_upssched_OBJECTS) upssched_DEPENDENCIES = ../common/libcommon.la \ ../common/libparseconf.la $(am__DEPENDENCIES_1) am_upsset_cgi_OBJECTS = upsset.$(OBJEXT) cgilib.$(OBJEXT) upsset_cgi_OBJECTS = $(am_upsset_cgi_OBJECTS) upsset_cgi_LDADD = $(LDADD) upsset_cgi_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_upsstats_cgi_OBJECTS = upsstats.$(OBJEXT) cgilib.$(OBJEXT) upsstats_cgi_OBJECTS = $(am_upsstats_cgi_OBJECTS) upsstats_cgi_LDADD = $(LDADD) upsstats_cgi_DEPENDENCIES = ../common/libcommon.la libupsclient.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) SCRIPTS = $(dist_bin_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libnutclient_la_SOURCES) $(libupsclient_la_SOURCES) \ $(upsc_SOURCES) $(upscmd_SOURCES) $(upsimage_cgi_SOURCES) \ $(upslog_SOURCES) $(upsmon_SOURCES) $(upsrw_SOURCES) \ $(upssched_SOURCES) $(upsset_cgi_SOURCES) \ $(upsstats_cgi_SOURCES) DIST_SOURCES = $(libnutclient_la_SOURCES) $(libupsclient_la_SOURCES) \ $(upsc_SOURCES) $(upscmd_SOURCES) $(upsimage_cgi_SOURCES) \ $(upslog_SOURCES) $(upsmon_SOURCES) $(upsrw_SOURCES) \ $(upssched_SOURCES) $(upsset_cgi_SOURCES) \ $(upsstats_cgi_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__include_HEADERS_DIST = upsclient.h ../include/parseconf.h \ nutclient.h HEADERS = $(include_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) A2X = @A2X@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ ASCIIDOC = @ASCIIDOC@ ASPELL = @ASPELL@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BINDIR = @BINDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CONFPATH = @CONFPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPUNIT_CFLAGS = @CPPUNIT_CFLAGS@ CPPUNIT_LIBS = @CPPUNIT_LIBS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBLATEX = @DBLATEX@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOC_BUILD_LIST = @DOC_BUILD_LIST@ DRIVER_BUILD_LIST = @DRIVER_BUILD_LIST@ DRIVER_INSTALL_TARGET = @DRIVER_INSTALL_TARGET@ DRIVER_MAN_LIST = @DRIVER_MAN_LIST@ DRVPATH = @DRVPATH@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAVAHI_CFLAGS = @LIBAVAHI_CFLAGS@ LIBAVAHI_LIBS = @LIBAVAHI_LIBS@ LIBGD_CFLAGS = @LIBGD_CFLAGS@ LIBGD_LDFLAGS = @LIBGD_LDFLAGS@ LIBIPMI_CFLAGS = @LIBIPMI_CFLAGS@ LIBIPMI_LIBS = @LIBIPMI_LIBS@ LIBLTDL_CFLAGS = @LIBLTDL_CFLAGS@ LIBLTDL_LIBS = @LIBLTDL_LIBS@ LIBNEON_CFLAGS = @LIBNEON_CFLAGS@ LIBNEON_LIBS = @LIBNEON_LIBS@ LIBNETSNMP_CFLAGS = @LIBNETSNMP_CFLAGS@ LIBNETSNMP_LIBS = @LIBNETSNMP_LIBS@ LIBOBJS = @LIBOBJS@ LIBPOWERMAN_CFLAGS = @LIBPOWERMAN_CFLAGS@ LIBPOWERMAN_LIBS = @LIBPOWERMAN_LIBS@ LIBS = @LIBS@ LIBSSL_CFLAGS = @LIBSSL_CFLAGS@ LIBSSL_LIBS = @LIBSSL_LIBS@ LIBTOOL = @LIBTOOL@ LIBUSB_CFLAGS = @LIBUSB_CFLAGS@ LIBUSB_LIBS = @LIBUSB_LIBS@ LIBWRAP_CFLAGS = @LIBWRAP_CFLAGS@ LIBWRAP_LIBS = @LIBWRAP_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NETLIBS = @NETLIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NUT_NETVERSION = @NUT_NETVERSION@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_NAME = @OS_NAME@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PIDPATH = @PIDPATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PORT = @PORT@ RANLIB = @RANLIB@ RUN_AS_GROUP = @RUN_AS_GROUP@ RUN_AS_USER = @RUN_AS_USER@ SBINDIR = @SBINDIR@ SED = @SED@ SERLIBS = @SERLIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STATEPATH = @STATEPATH@ STRIP = @STRIP@ SUN_LIBUSB = @SUN_LIBUSB@ TREE_VERSION = @TREE_VERSION@ VERSION = @VERSION@ WORDS_BIGENDIAN = @WORDS_BIGENDIAN@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ cgiexecdir = @cgiexecdir@ datadir = @datadir@ datarootdir = @datarootdir@ devddir = @devddir@ docdir = @docdir@ driverexecdir = @driverexecdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ hotplugdir = @hotplugdir@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ systemdsystemshutdowndir = @systemdsystemshutdowndir@ systemdsystemunitdir = @systemdsystemunitdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ udevdir = @udevdir@ # by default, link programs in this directory with libcommon.a LDADD = ../common/libcommon.la libupsclient.la $(NETLIBS) \ $(am__append_1) # Avoid per-target CFLAGS, because this will prevent re-use of object # files. In any case, CFLAGS are only -I options, so there is no harm, # but only add them if we really use the target. AM_CFLAGS = -I$(top_srcdir)/include $(am__append_2) $(am__append_3) dist_bin_SCRIPTS = upssched-cmd lib_LTLIBRARIES = libupsclient.la libnutclient.la @WITH_DEV_TRUE@include_HEADERS = upsclient.h ../include/parseconf.h nutclient.h upsc_SOURCES = upsc.c upsclient.h upscmd_SOURCES = upscmd.c upsclient.h upsrw_SOURCES = upsrw.c upsclient.h upslog_SOURCES = upslog.c upsclient.h upslog.h upsmon_SOURCES = upsmon.c upsmon.h upsclient.h upssched_SOURCES = upssched.c upssched.h upssched_LDADD = ../common/libcommon.la ../common/libparseconf.la $(NETLIBS) upsimage_cgi_SOURCES = upsimage.c upsclient.h upsimagearg.h cgilib.c cgilib.h upsimage_cgi_LDADD = $(LDADD) $(LIBGD_LDFLAGS) upsset_cgi_SOURCES = upsset.c upsclient.h cgilib.c cgilib.h upsstats_cgi_SOURCES = upsstats.c upsclient.h status.h upsstats.h \ upsimagearg.h cgilib.c cgilib.h # not LDADD. libupsclient_la_SOURCES = upsclient.c upsclient.h libupsclient_la_LIBADD = ../common/libcommonclient.la $(am__append_4) # libupsclient version information # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html libupsclient_la_LDFLAGS = -version-info 4:0:0 libnutclient_la_SOURCES = nutclient.h nutclient.cpp libnutclient_la_LDFLAGS = -version-info 0:0:0 all: all-am .SUFFIXES: .SUFFIXES: .c .cpp .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu clients/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu clients/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libnutclient.la: $(libnutclient_la_OBJECTS) $(libnutclient_la_DEPENDENCIES) $(EXTRA_libnutclient_la_DEPENDENCIES) $(libnutclient_la_LINK) -rpath $(libdir) $(libnutclient_la_OBJECTS) $(libnutclient_la_LIBADD) $(LIBS) libupsclient.la: $(libupsclient_la_OBJECTS) $(libupsclient_la_DEPENDENCIES) $(EXTRA_libupsclient_la_DEPENDENCIES) $(libupsclient_la_LINK) -rpath $(libdir) $(libupsclient_la_OBJECTS) $(libupsclient_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-cgiexecPROGRAMS: $(cgiexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(cgiexec_PROGRAMS)'; test -n "$(cgiexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(cgiexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(cgiexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(cgiexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(cgiexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-cgiexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(cgiexec_PROGRAMS)'; test -n "$(cgiexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(cgiexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(cgiexecdir)" && rm -f $$files clean-cgiexecPROGRAMS: @list='$(cgiexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list upsc$(EXEEXT): $(upsc_OBJECTS) $(upsc_DEPENDENCIES) $(EXTRA_upsc_DEPENDENCIES) @rm -f upsc$(EXEEXT) $(LINK) $(upsc_OBJECTS) $(upsc_LDADD) $(LIBS) upscmd$(EXEEXT): $(upscmd_OBJECTS) $(upscmd_DEPENDENCIES) $(EXTRA_upscmd_DEPENDENCIES) @rm -f upscmd$(EXEEXT) $(LINK) $(upscmd_OBJECTS) $(upscmd_LDADD) $(LIBS) upsimage.cgi$(EXEEXT): $(upsimage_cgi_OBJECTS) $(upsimage_cgi_DEPENDENCIES) $(EXTRA_upsimage_cgi_DEPENDENCIES) @rm -f upsimage.cgi$(EXEEXT) $(LINK) $(upsimage_cgi_OBJECTS) $(upsimage_cgi_LDADD) $(LIBS) upslog$(EXEEXT): $(upslog_OBJECTS) $(upslog_DEPENDENCIES) $(EXTRA_upslog_DEPENDENCIES) @rm -f upslog$(EXEEXT) $(LINK) $(upslog_OBJECTS) $(upslog_LDADD) $(LIBS) upsmon$(EXEEXT): $(upsmon_OBJECTS) $(upsmon_DEPENDENCIES) $(EXTRA_upsmon_DEPENDENCIES) @rm -f upsmon$(EXEEXT) $(LINK) $(upsmon_OBJECTS) $(upsmon_LDADD) $(LIBS) upsrw$(EXEEXT): $(upsrw_OBJECTS) $(upsrw_DEPENDENCIES) $(EXTRA_upsrw_DEPENDENCIES) @rm -f upsrw$(EXEEXT) $(LINK) $(upsrw_OBJECTS) $(upsrw_LDADD) $(LIBS) upssched$(EXEEXT): $(upssched_OBJECTS) $(upssched_DEPENDENCIES) $(EXTRA_upssched_DEPENDENCIES) @rm -f upssched$(EXEEXT) $(LINK) $(upssched_OBJECTS) $(upssched_LDADD) $(LIBS) upsset.cgi$(EXEEXT): $(upsset_cgi_OBJECTS) $(upsset_cgi_DEPENDENCIES) $(EXTRA_upsset_cgi_DEPENDENCIES) @rm -f upsset.cgi$(EXEEXT) $(LINK) $(upsset_cgi_OBJECTS) $(upsset_cgi_LDADD) $(LIBS) upsstats.cgi$(EXEEXT): $(upsstats_cgi_OBJECTS) $(upsstats_cgi_DEPENDENCIES) $(EXTRA_upsstats_cgi_DEPENDENCIES) @rm -f upsstats.cgi$(EXEEXT) $(LINK) $(upsstats_cgi_OBJECTS) $(upsstats_cgi_LDADD) $(LIBS) install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgilib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nutclient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsclient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upscmd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upslog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsmon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsrw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upssched.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsset.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upsstats.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-includeHEADERS: $(include_HEADERS) @$(NORMAL_INSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ done uninstall-includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(cgiexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-cgiexecPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-cgiexecPROGRAMS \ install-dist_binSCRIPTS install-libLTLIBRARIES \ install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-cgiexecPROGRAMS \ uninstall-dist_binSCRIPTS uninstall-includeHEADERS \ uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-cgiexecPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-sbinPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-cgiexecPROGRAMS \ install-data install-data-am install-dist_binSCRIPTS \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-includeHEADERS \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-sbinPROGRAMS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-cgiexecPROGRAMS uninstall-dist_binSCRIPTS \ uninstall-includeHEADERS uninstall-libLTLIBRARIES \ uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: nut-2.7.2/clients/upsclient.h0000644000175000017500000001414312277355125013105 00000000000000/* upsclient.h - definitions for upsclient functions Copyright (C) 2002 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef UPSCLIENT_H_SEEN #define UPSCLIENT_H_SEEN #ifdef WITH_OPENSSL #include #include #elif defined(WITH_NSS) /* WITH_OPENSSL */ #include #include #endif /* WITH_OPENSSL | WITH_NSS */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif #define UPSCLI_ERRBUF_LEN 256 #define UPSCLI_NETBUF_LEN 512 /* network i/o buffer */ #include "parseconf.h" typedef struct { char *host; int port; int fd; int flags; int upserror; int syserrno; int upsclient_magic; PCONF_CTX_t pc_ctx; char errbuf[UPSCLI_ERRBUF_LEN]; #ifdef WITH_OPENSSL SSL *ssl; #elif defined(WITH_NSS) /* WITH_OPENSSL */ PRFileDesc *ssl; #else /* WITH_OPENSSL | WITH_NSS */ void *ssl; #endif /* WITH_OPENSSL | WITH_NSS */ char readbuf[64]; size_t readlen; size_t readidx; } UPSCONN_t; const char *upscli_strerror(UPSCONN_t *ups); int upscli_init(int certverify, const char *certpath, const char *certname, const char *certpasswd); int upscli_cleanup(); int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags, struct timeval *tv); int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags); void upscli_add_host_cert(const char* hostname, const char* certname, int certverify, int forcessl); /* --- functions that only use the new names --- */ int upscli_get(UPSCONN_t *ups, unsigned int numq, const char **query, unsigned int *numa, char ***answer); int upscli_list_start(UPSCONN_t *ups, unsigned int numq, const char **query); int upscli_list_next(UPSCONN_t *ups, unsigned int numq, const char **query, unsigned int *numa, char ***answer); int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen); int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen); int upscli_splitname(const char *buf, char **upsname, char **hostname, int *port); int upscli_splitaddr(const char *buf, char **hostname, int *port); int upscli_disconnect(UPSCONN_t *ups); /* these functions return elements from UPSCONN_t to avoid direct references */ int upscli_fd(UPSCONN_t *ups); int upscli_upserror(UPSCONN_t *ups); /* returns 1 if SSL mode is active for this connection */ int upscli_ssl(UPSCONN_t *ups); /* upsclient error list */ #define UPSCLI_ERR_UNKNOWN 0 /* Unknown error */ #define UPSCLI_ERR_VARNOTSUPP 1 /* Variable not supported by UPS */ #define UPSCLI_ERR_NOSUCHHOST 2 /* No such host */ #define UPSCLI_ERR_INVRESP 3 /* Invalid response from server */ #define UPSCLI_ERR_UNKNOWNUPS 4 /* Unknown UPS */ #define UPSCLI_ERR_INVLISTTYPE 5 /* Invalid list type */ #define UPSCLI_ERR_ACCESSDENIED 6 /* Access denied */ #define UPSCLI_ERR_PWDREQUIRED 7 /* Password required */ #define UPSCLI_ERR_PWDINCORRECT 8 /* Password incorrect */ #define UPSCLI_ERR_MISSINGARG 9 /* Missing argument */ #define UPSCLI_ERR_DATASTALE 10 /* Data stale */ #define UPSCLI_ERR_VARUNKNOWN 11 /* Variable unknown */ #define UPSCLI_ERR_LOGINTWICE 12 /* Already logged in */ #define UPSCLI_ERR_PWDSETTWICE 13 /* Already set password */ #define UPSCLI_ERR_UNKNOWNTYPE 14 /* Unknown variable type */ #define UPSCLI_ERR_UNKNOWNVAR 15 /* Unknown variable */ #define UPSCLI_ERR_VARREADONLY 16 /* Read-only variable */ #define UPSCLI_ERR_TOOLONG 17 /* New value is too long */ #define UPSCLI_ERR_INVALIDVALUE 18 /* Invalid value for variable */ #define UPSCLI_ERR_SETFAILED 19 /* Set command failed */ #define UPSCLI_ERR_UNKINSTCMD 20 /* Unknown instant command */ #define UPSCLI_ERR_CMDFAILED 21 /* Instant command failed */ #define UPSCLI_ERR_CMDNOTSUPP 22 /* Instant command not supported */ #define UPSCLI_ERR_INVUSERNAME 23 /* Invalid username */ #define UPSCLI_ERR_USERSETTWICE 24 /* Already set username */ #define UPSCLI_ERR_UNKCOMMAND 25 /* Unknown command */ #define UPSCLI_ERR_INVALIDARG 26 /* Invalid argument */ #define UPSCLI_ERR_SENDFAILURE 27 /* Send failure: %s */ #define UPSCLI_ERR_RECVFAILURE 28 /* Receive failure: %s */ #define UPSCLI_ERR_SOCKFAILURE 29 /* socket failure: %s */ #define UPSCLI_ERR_BINDFAILURE 30 /* bind failure: %s */ #define UPSCLI_ERR_CONNFAILURE 31 /* Connection failure: %s */ #define UPSCLI_ERR_WRITE 32 /* Write error: %s */ #define UPSCLI_ERR_READ 33 /* Read error: %s */ #define UPSCLI_ERR_INVPASSWORD 34 /* Invalid password */ #define UPSCLI_ERR_USERREQUIRED 35 /* Username required */ #define UPSCLI_ERR_SSLFAIL 36 /* SSL is not available */ #define UPSCLI_ERR_SSLERR 37 /* SSL error: %s */ #define UPSCLI_ERR_SRVDISC 38 /* Server disconnected */ #define UPSCLI_ERR_DRVNOTCONN 39 /* Driver not connected */ #define UPSCLI_ERR_NOMEM 40 /* Memory allocation failure */ #define UPSCLI_ERR_PARSE 41 /* Parse error: %s */ #define UPSCLI_ERR_PROTOCOL 42 /* Protocol error */ #define UPSCLI_ERR_MAX 42 /* stop here */ /* list types for use with upscli_getlist */ #define UPSCLI_LIST_VARS 1 /* all variables */ #define UPSCLI_LIST_RW 2 /* just read/write variables */ #define UPSCLI_LIST_CMDS 3 /* instant commands */ /* flags for use with upscli_connect */ #define UPSCLI_CONN_TRYSSL 0x0001 /* try SSL, OK if not supported */ #define UPSCLI_CONN_REQSSL 0x0002 /* try SSL, fail if not supported */ #define UPSCLI_CONN_INET 0x0004 /* IPv4 only */ #define UPSCLI_CONN_INET6 0x0008 /* IPv6 only */ #define UPSCLI_CONN_CERTVERIF 0x0010 /* Verify certificates for SSL */ #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #endif /* UPSCLIENT_H_SEEN */ nut-2.7.2/clients/upsrw.c0000644000175000017500000002710512303134465012244 00000000000000/* upsrw - simple client for read/write variable access (formerly upsct2) Copyright (C) 1999 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut_platform.h" #include #include #include #include #include "upsclient.h" static char *upsname = NULL, *hostname = NULL; static UPSCONN_t *ups = NULL; struct list_t { char *name; struct list_t *next; }; static void usage(const char *prog) { printf("Network UPS Tools %s %s\n\n", prog, UPS_VERSION); printf("usage: %s [-h]\n", prog); printf(" %s [-s ] [-u ] [-p ] \n\n", prog); printf("Demo program to set variables within UPS hardware.\n"); printf("\n"); printf(" -h display this help text\n"); printf(" -s specify variable to be changed\n"); printf(" use -s VAR=VALUE to avoid prompting for value\n"); printf(" -u set username for command authentication\n"); printf(" -p set password for command authentication\n"); printf("\n"); printf(" UPS identifier - [@[:]]\n"); printf("\n"); printf("Call without -s to show all possible read/write variables.\n"); } static void clean_exit(void) { if (ups) { upscli_disconnect(ups); } free(upsname); free(hostname); free(ups); } static void do_set(const char *varname, const char *newval) { char buf[SMALLBUF], enc[SMALLBUF]; snprintf(buf, sizeof(buf), "SET VAR %s %s \"%s\"\n", upsname, varname, pconf_encode(newval, enc, sizeof(enc))); if (upscli_sendline(ups, buf, strlen(buf)) < 0) { fatalx(EXIT_FAILURE, "Can't set variable: %s", upscli_strerror(ups)); } if (upscli_readline(ups, buf, sizeof(buf)) < 0) { fatalx(EXIT_FAILURE, "Set variable failed: %s", upscli_strerror(ups)); } /* FUTURE: status cookies will tie in here */ if (strncmp(buf, "OK", 2) != 0) { fatalx(EXIT_FAILURE, "Unexpected response from upsd: %s", buf); } fprintf(stderr, "%s\n", buf); } static void do_setvar(const char *varname, char *uin, const char *pass) { char newval[SMALLBUF], temp[SMALLBUF], user[SMALLBUF], *ptr; struct passwd *pw; if (uin) { snprintf(user, sizeof(user), "%s", uin); } else { memset(user, '\0', sizeof(user)); pw = getpwuid(getuid()); if (pw) { printf("Username (%s): ", pw->pw_name); } else { printf("Username: "); } if (fgets(user, sizeof(user), stdin) == NULL) { upsdebug_with_errno(LOG_INFO, "%s", __func__); } /* deal with that pesky newline */ if (strlen(user) > 1) { user[strlen(user) - 1] = '\0'; } else { if (!pw) { fatalx(EXIT_FAILURE, "No username available - even tried getpwuid"); } snprintf(user, sizeof(user), "%s", pw->pw_name); } } /* leaks - use -p when running in valgrind */ if (!pass) { pass = GETPASS("Password: " ); if (!pass) { fatal_with_errno(EXIT_FAILURE, "getpass failed"); } } /* Check if varname is in VAR=VALUE form */ if ((ptr = strchr(varname, '=')) != NULL) { *ptr++ = 0; snprintf(newval, sizeof(newval), "%s", ptr); } else { printf("Enter new value for %s: ", varname); fflush(stdout); if (fgets(newval, sizeof(newval), stdin) == NULL) { upsdebug_with_errno(LOG_INFO, "%s", __func__); } newval[strlen(newval) - 1] = '\0'; } snprintf(temp, sizeof(temp), "USERNAME %s\n", user); if (upscli_sendline(ups, temp, strlen(temp)) < 0) { fatalx(EXIT_FAILURE, "Can't set username: %s", upscli_strerror(ups)); } if (upscli_readline(ups, temp, sizeof(temp)) < 0) { if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Set username failed due to an unknown command. You probably need to upgrade upsd."); } fatalx(EXIT_FAILURE, "Set username failed: %s", upscli_strerror(ups)); } snprintf(temp, sizeof(temp), "PASSWORD %s\n", pass); if (upscli_sendline(ups, temp, strlen(temp)) < 0) { fatalx(EXIT_FAILURE, "Can't set password: %s", upscli_strerror(ups)); } if (upscli_readline(ups, temp, sizeof(temp)) < 0) { fatalx(EXIT_FAILURE, "Set password failed: %s", upscli_strerror(ups)); } /* no upsname means die */ if (!upsname) { fatalx(EXIT_FAILURE, "Error: a UPS name must be specified (upsname[@hostname[:port]])"); } /* old variable names are no longer supported */ if (!strchr(varname, '.')) { fatalx(EXIT_FAILURE, "Error: old variable names are not supported"); } do_set(varname, newval); } static const char *get_data(const char *type, const char *varname) { int ret; unsigned int numq, numa; char **answer; const char *query[4]; query[0] = type; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_get(ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) { return NULL; } /* */ return answer[3]; } static void do_string(const char *varname, const int len) { const char *val; val = get_data("VAR", varname); if (!val) { fatalx(EXIT_FAILURE, "do_string: can't get current value of %s", varname); } printf("Type: STRING\n"); printf("Maximum length: %d\n", len); printf("Value: %s\n", val); } static void do_enum(const char *varname) { int ret; unsigned int numq, numa; char **answer, buf[SMALLBUF]; const char *query[4], *val; /* get current value */ val = get_data("VAR", varname); if (!val) { fatalx(EXIT_FAILURE, "do_enum: can't get current value of %s", varname); } snprintf(buf, sizeof(buf), "%s", val); query[0] = "ENUM"; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_list_start(ups, numq, query); if (ret < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } ret = upscli_list_next(ups, numq, query, &numa, &answer); printf("Type: ENUM\n"); while (ret == 1) { /* ENUM */ if (numa < 4) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa); } printf("Option: \"%s\"", answer[3]); if (!strcmp(answer[3], buf)) { printf(" SELECTED"); } printf("\n"); ret = upscli_list_next(ups, numq, query, &numa, &answer); } } static void do_range(const char *varname) { int ret; unsigned int numq, numa; char **answer; const char *query[4], *val; int ival, min, max; /* get current value */ val = get_data("VAR", varname); if (!val) { fatalx(EXIT_FAILURE, "do_range: can't get current value of %s", varname); } ival = atoi(val); query[0] = "RANGE"; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_list_start(ups, numq, query); if (ret < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } ret = upscli_list_next(ups, numq, query, &numa, &answer); printf("Type: RANGE\n"); while (ret == 1) { /* RANGE */ if (numa < 5) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa); } min = atoi(answer[3]); max = atoi(answer[4]); printf("Option: \"%i-%i\"", min, max); if ((ival >= min) && (ival <= max)) { printf(" SELECTED"); } printf("\n"); ret = upscli_list_next(ups, numq, query, &numa, &answer); } } static void do_type(const char *varname) { int ret; unsigned int i, numq, numa; char **answer; const char *query[4]; query[0] = "TYPE"; query[1] = upsname; query[2] = varname; numq = 3; ret = upscli_get(ups, numq, query, &numa, &answer); if ((ret < 0) || (numa < numq)) { printf("Unknown type\n"); return; } /* TYPE ... */ for (i = 3; i < numa; i++) { if (!strcasecmp(answer[i], "ENUM")) { do_enum(varname); return; } if (!strcasecmp(answer[i], "RANGE")) { do_range(varname); return; } if (!strncasecmp(answer[i], "STRING:", 7)) { char *len = answer[i] + 7; int length = strtol(len, NULL, 10); do_string(varname, length); return; } /* ignore this one */ if (!strcasecmp(answer[i], "RW")) { continue; } printf("Type: %s (unrecognized)\n", answer[i]); } } static void print_rw(const char *varname) { const char *tmp; printf("[%s]\n", varname); tmp = get_data("DESC", varname); if (tmp) { printf("%s\n", tmp); } else { printf("Description unavailable\n"); } do_type(varname); printf("\n"); } static void print_rwlist(void) { int ret; unsigned int numq, numa; const char *query[2]; char **answer; struct list_t *lhead, *llast, *ltmp, *lnext; /* the upsname is now required */ if (!upsname) { fatalx(EXIT_FAILURE, "Error: a UPS name must be specified (upsname[@hostname[:port]])"); } llast = lhead = NULL; query[0] = "RW"; query[1] = upsname; numq = 2; ret = upscli_list_start(ups, numq, query); if (ret < 0) { /* old upsd --> fall back on old LISTRW technique */ if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query"); } fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } ret = upscli_list_next(ups, numq, query, &numa, &answer); while (ret == 1) { /* RW */ if (numa < 4) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa); } /* sock this entry away for later */ ltmp = xmalloc(sizeof(struct list_t)); ltmp->name = xstrdup(answer[2]); ltmp->next = NULL; if (llast) { llast->next = ltmp; } else { lhead = ltmp; } llast = ltmp; ret = upscli_list_next(ups, numq, query, &numa, &answer); } /* use the list to get descriptions and types */ ltmp = lhead; while (ltmp) { lnext = ltmp->next; print_rw(ltmp->name); free(ltmp->name); free(ltmp); ltmp = lnext; } } int main(int argc, char **argv) { int i, port; const char *prog = xbasename(argv[0]); char *password = NULL, *username = NULL, *setvar = NULL; while ((i = getopt(argc, argv, "+hs:p:u:V")) != -1) { switch (i) { case 's': setvar = optarg; break; case 'p': password = optarg; break; case 'u': username = optarg; break; case 'V': printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); exit(EXIT_SUCCESS); case 'h': default: usage(prog); exit(EXIT_SUCCESS); } } argc -= optind; argv += optind; if (argc < 1) { usage(prog); exit(EXIT_SUCCESS); } /* be a good little client that cleans up after itself */ atexit(clean_exit); if (upscli_splitname(argv[0], &upsname, &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]"); } ups = xcalloc(1, sizeof(*ups)); if (upscli_connect(ups, hostname, port, 0) < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } if (setvar) { /* setting a variable */ do_setvar(setvar, username, password); } else { /* if not, get the list of supported read/write variables */ print_rwlist(); } exit(EXIT_SUCCESS); } /* Formal do_upsconf_args implementation to satisfy linker on AIX */ #if (defined NUT_PLATFORM_AIX) void do_upsconf_args(char *upsname, char *var, char *val) { fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called"); } #endif /* end of #if (defined NUT_PLATFORM_AIX) */ nut-2.7.2/clients/cgilib.h0000644000175000017500000000245612277355125012334 00000000000000/* cgilib.h - headers for cgilib.c Copyright (C) 1999 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* other programs that link to this should provide parsearg() ... */ void parsearg(char *var, char *value); /* actually extract the values from QUERY_STRING */ void extractcgiargs(void); /* like extractcgiargs, but this one is for POSTed values */ void extractpostargs(void); /* see if a host is allowed per the hosts.conf */ int checkhost(const char *host, char **desc); #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif nut-2.7.2/clients/upsc.c0000644000175000017500000001543112301203176012027 00000000000000/* upsc - simple "client" to test communications Copyright (C) 1999 Russell Kroll Copyright (C) 2012 Arnaud Quette This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include "nut_platform.h" #include #include #include #include "upsclient.h" static char *upsname = NULL, *hostname = NULL; static UPSCONN_t *ups = NULL; static void usage(const char *prog) { printf("Network UPS Tools upsc %s\n\n", UPS_VERSION); printf("usage: %s -l | -L [[:port]]\n", prog); printf(" %s []\n", prog); printf(" %s -c \n", prog); printf("\nDemo program to display UPS variables.\n\n"); printf("First form (lists UPSes):\n"); printf(" -l - lists each UPS on , one per line.\n"); printf(" -L - lists each UPS followed by its description (from ups.conf).\n"); printf(" Default hostname: localhost\n"); printf("\nSecond form (lists variables and values):\n"); printf(" - upsd server, [@[:]] form\n"); printf(" - optional, display this variable only.\n"); printf(" Default: list all variables for \n"); printf("\nThird form (lists clients connected to a device):\n"); printf(" -c - lists each client connected on , one per line.\n"); printf(" - upsd server, [@[:]] form\n"); } static void printvar(const char *var) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; /* old-style variable name? */ if (!strchr(var, '.')) { fatalx(EXIT_FAILURE, "Error: old-style variable names are not supported"); } query[0] = "VAR"; query[1] = upsname; query[2] = var; numq = 3; ret = upscli_get(ups, numq, query, &numa, &answer); if (ret < 0) { /* new var and old upsd? try to explain the situation */ if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Error: variable unknown (old upsd detected)"); } fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } if (numa < numq) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least %d)", numa, numq); } printf("%s\n", answer[3]); } static void list_vars(void) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; query[0] = "VAR"; query[1] = upsname; numq = 2; ret = upscli_list_start(ups, numq, query); if (ret < 0) { /* check for an old upsd */ if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query"); } fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } while (upscli_list_next(ups, numq, query, &numa, &answer) == 1) { /* VAR */ if (numa < 4) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 4)", numa); } printf("%s: %s\n", answer[2], answer[3]); } } static void list_upses(int verbose) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; query[0] = "UPS"; numq = 1; ret = upscli_list_start(ups, numq, query); if (ret < 0) { /* check for an old upsd */ if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query"); } fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } while (upscli_list_next(ups, numq, query, &numa, &answer) == 1) { /* UPS */ if (numa < 3) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa); } if(verbose) { printf("%s: %s\n", answer[1], answer[2]); } else { printf("%s\n", answer[1]); } } } static void list_clients(const char *devname) { int ret; unsigned int numq, numa; const char *query[4]; char **answer; query[0] = "CLIENT"; query[1] = devname; numq = 2; ret = upscli_list_start(ups, numq, query); if (ret < 0) { /* check for an old upsd */ if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND) { fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query"); } fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } while ((ret=upscli_list_next(ups, numq, query, &numa, &answer)) == 1) { /* CLIENT
*/ if (numa < 3) { fatalx(EXIT_FAILURE, "Error: insufficient data (got %d args, need at least 3)", numa); } printf("%s\n", answer[2]); } } static void clean_exit(void) { if (ups) { upscli_disconnect(ups); } free(upsname); free(hostname); free(ups); } int main(int argc, char **argv) { int i, port; int varlist = 0, clientlist = 0, verbose = 0; const char *prog = xbasename(argv[0]); while ((i = getopt(argc, argv, "+hlLcV")) != -1) { switch (i) { case 'L': verbose = 1; case 'l': varlist = 1; break; case 'c': clientlist = 1; break; case 'V': fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); case 'h': default: usage(prog); exit(EXIT_SUCCESS); } } argc -= optind; argv += optind; /* be a good little client that cleans up after itself */ atexit(clean_exit); if (varlist) { if (upscli_splitaddr(argv[0] ? argv[0] : "localhost", &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid hostname.\nRequired format: [hostname[:port]]"); } } else { if (upscli_splitname(argv[0], &upsname, &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition.\nRequired format: upsname[@hostname[:port]]"); } } ups = xmalloc(sizeof(*ups)); if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) { fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups)); } if (varlist) { list_upses(verbose); exit(EXIT_SUCCESS); } if (clientlist) { list_clients(upsname); exit(EXIT_SUCCESS); } if (argc > 1) { printvar(argv[1]); } else { list_vars(); } exit(EXIT_SUCCESS); } /* Formal do_upsconf_args implementation to satisfy linker on AIX */ #if (defined NUT_PLATFORM_AIX) void do_upsconf_args(char *upsname, char *var, char *val) { fatalx(EXIT_FAILURE, "INTERNAL ERROR: formal do_upsconf_args called"); } #endif /* end of #if (defined NUT_PLATFORM_AIX) */ nut-2.7.2/clients/upssched.c0000644000175000017500000004443312301203176012677 00000000000000/* upssched.c - upsmon's scheduling helper for offset timers Copyright (C) 2000 Russell Kroll This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* design notes for the curious: * * 1. we get called with a upsname and notifytype from upsmon * 2. the config file is searched for an AT condition that matches * 3. the conditions on any matching lines are parsed * * starting a timer: the timer is added to the daemon's timer queue * cancelling a timer: the timer is removed from that queue * execute a command: the command is passed straight to the cmdscript * * if the daemon is not already running and is required (to start a timer) * it will be started automatically * * when the time arrives, the command associated with a timer will be * executed by the daemon (via the cmdscript) * * timers can be cancelled at any time before they trigger * * the daemon will shut down automatically when no more timers are active * */ #include "common.h" #include #include #include #include #include #include "upssched.h" #include "timehead.h" typedef struct ttype_s { char *name; time_t etime; struct ttype_s *next; } ttype_t; ttype_t *thead = NULL; static conn_t *connhead = NULL; char *cmdscript = NULL, *pipefn = NULL, *lockfn = NULL; int verbose = 0; /* use for debugging */ /* ups name and notify type (string) as received from upsmon */ const char *upsname, *notify_type; #define PARENT_STARTED -2 #define PARENT_UNNECESSARY -3 #define MAX_TRIES 30 #define EMPTY_WAIT 15 /* min passes with no timers to exit */ #define US_LISTEN_BACKLOG 16 #define US_SOCK_BUF_LEN 256 #define US_MAX_READ 128 /* --- server functions --- */ static void exec_cmd(const char *cmd) { int err; char buf[LARGEBUF]; snprintf(buf, sizeof(buf), "%s %s", cmdscript, cmd); err = system(buf); if (WIFEXITED(err)) { if (WEXITSTATUS(err)) { upslogx(LOG_INFO, "exec_cmd(%s) returned %d", buf, WEXITSTATUS(err)); } } else { if (WIFSIGNALED(err)) { upslogx(LOG_WARNING, "exec_cmd(%s) terminated with signal %d", buf, WTERMSIG(err)); } else { upslogx(LOG_ERR, "Execute command failure: %s", buf); } } return; } static void removetimer(ttype_t *tfind) { ttype_t *tmp, *last; last = NULL; tmp = thead; while (tmp) { if (tmp == tfind) { /* found it */ if (last == NULL) /* deleting first */ thead = tmp->next; else last->next = tmp->next; free(tmp->name); free(tmp); return; } last = tmp; tmp = tmp->next; } /* this one should never happen */ upslogx(LOG_ERR, "removetimer: failed to locate target at %p", (void *)tfind); } static void checktimers(void) { ttype_t *tmp, *tmpnext; time_t now; static int emptyctr = 0; /* if the queue is empty we might be ready to exit */ if (!thead) { emptyctr++; /* wait a little while in case someone wants us again */ if (emptyctr < EMPTY_WAIT) return; if (verbose) upslogx(LOG_INFO, "Timer queue empty, exiting"); #ifdef UPSSCHED_RACE_TEST upslogx(LOG_INFO, "triggering race: sleeping 15 sec before exit"); sleep(15); #endif unlink(pipefn); exit(EXIT_SUCCESS); } emptyctr = 0; /* flip through LL, look for activity */ tmp = thead; time(&now); while (tmp) { tmpnext = tmp->next; if (now >= tmp->etime) { if (verbose) upslogx(LOG_INFO, "Event: %s ", tmp->name); exec_cmd(tmp->name); /* delete from queue */ removetimer(tmp); } tmp = tmpnext; } } static void start_timer(const char *name, const char *ofsstr) { time_t now; int ofs; ttype_t *tmp, *last; /* get the time */ time(&now); /* add an event for +