[bug#75528,2/2] services: Add power.

Message ID 87r03vycdh.fsf@gmail.com
State New
Headers
Series None |

Commit Message

Maxim Cournoyer Feb. 18, 2025, 6:51 a.m. UTC
  Hi Tomas,

Tomas Volf <~@wolfsden.cz> writes:

[...]

>> Deprecating /var/run to /run is not a Guix thing, but a File Hiearchy
>> Standard (FHS) thing [0].  Since we already use /run, there's no good
>> reason to have /var/run something else than a symlink to /run, and
>> there's an actual change pending merge that would do that, along making
>> /run mounted as a tmpfs (bug#73494).
>>
>> [0]  https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05s13.html
>
> I did not know we actually care about FHS (for example our /usr/bin
> definitely does not look like it should in that case :) ).
>
> I did the s|/var/run|/run|.

We typically do not follow FHS much due to each of our packages being
installed under their own prefix, but for the few things where we do,
like here, I think it makes sense to stick to it, as it brings
familiarity and consistency to our users.

>>>> s/Slave/slave/ ?  Could be nicer to use a neutral alternative like
>>>> 'follower machine'.
>>>
>>> The "Slave machine" (including the capitalization) is a term used in the
>>> manual.  I can lower-case it if you would prefer, seems that manual
>>> actually uses both casings now when I looked for it.
>>>
>>> I do not think inventing new terminology is a good idea, since users
>>> will not be able to find it in the manual distributed with the program.
>>
>> The 'slave' word always carry a negative connotation.  I think it's a
>> good idea to be proactive on modernizing the terminology where we can.
>
> In that case I would suggest to contact the upstream and convince them
> regarding this topic.  Once that happens, we will be able to adjust the
> documentation with the next release (which would be free of offensive
> terminology).
>
> In any case, this is not a first occurrence of the word "slave" in the
> Guix repository nor manual.

That there are currently other occurrences is not a good reason to add
more, in my opinion :-).  That said, I've looked at upstream sources and
it's true that the old master/slave terminology is currently deeply
interwined in code and doc... so I did an experiment and came up with
<https://codeberg.org/apteryx/acupsd/pulls/1>.  I also forwarded the
svn diff to upstream via their mailing list.  We'll see what they think.


[...]

>>> WARNING: (guile-user): imported module (gnu services) overrides core binding `delete'
>>>
>>> However, when done "my" way (putting srfi-1 first, since "stdlib"), the
>>> warning goes away.
>>
>> That's an interesting workaround, but I think we should look into that
>> problem and fix it definitely I often used #:hidden (delete) without any
>> issue it seems, so I'm not even sure if its existence still solves a
>> true problem in current Guile.
>
> I have recently (~few months back) tried to remove the `delete' and it a
> wall quickly, so I assume for reasons I do not understand it is still
> required.
>
> Having to use #:hidden (delete) on every single relevant import is in my
> opinion much worse solution than just ordering imports with srfi-1 at
> the top.
>
> But, I concur, it would be best it this just worked in any order.

OK, good to know, but let's keep this out of scope for the context of
this change.

> Anyway, I have sorted the modules as requested.  I am not sure whether
> to sort
>
> #$@(apcupsd-event-handlers-modules
>     (apcupsd-configuration-event-handlers cfg))
>
>
> Under `a' or `m' though.  Opinion?

I'm not sure I understood the question, but under `a' makes more sense
to me (which `m' are you referring to?).

>>>>> +(define-configuration/no-serialization apcupsd-event-handlers
>>>>> +  (killpower
>>>>> +   (gexp
>>>>> +    #~((wall "Apccontrol doing: apcupsd --killpower on UPS ~a" name)
>>>>> +       (sleep 10)
>>>>> +       (apcupsd "--killpower")
>>>>> +       (wall "Apccontrol has done: apcupsd --killpower on UPS ~a" name)))
>>>>> +   "Handler for killpower event.")
>>>>
>>
>> By the way, why do we need to sleep 10 seconds here?  It seems
>> unnecessary.
>
> All default handlers are just conversions of the official apccontrol
> script, and it has the sleep in there.  I am not sure why, so I have
> decided it would be better to leave it as it was.

OK, I guess it's safer to keep it.

>> I just thought about it, perhaps it could be more concise to extract the
>> field values using match-record (these are bound to shorter names, since
>> they omit the 'apcupsd-configuration-' prefix).
>
> If I got the idea right, you suggest converting
>
> 	      ("emergency"
> 	       #$@(apcupsd-event-handlers-emergency
> 		   (apcupsd-configuration-event-handlers cfg)))
>
>
> into
>
> 	      ("emergency"
> 	       #$@(match-record cfg <apcupsd-configuration> (handlers)
>                     (match-record handlers <apcupsd-event-handlers> (emergency)
>                       emergency)))
>
>
> I am not sure it is increase in readability, but maybe I misunderstood
> the suggestion.

I think something like this should work:

--8<---------------cut here---------------start------------->8---
modified   gnu/services/power.scm
@@ -494,119 +494,67 @@ (define-configuration apcupsd-configuration
    empty-serializer))
 
 (define (%apccontrol config)
-  (program-file
-   "apccontrol"
-   #~(begin
-       (use-modules (ice-9 format)
-                    (ice-9 match)
-                    (ice-9 popen)
-                    (srfi srfi-9)
-                    #$@(apcupsd-event-handlers-modules
-                        (apcupsd-configuration-event-handlers config)))
-       ;; Script dir depends on these, and the configuration depends on the
-       ;; script dir.  To sever the cyclic dependency, pass the file names via
-       ;; environment variables.
-       (define conf (getenv "GUIX_APCUPSD_CONF"))
-       (define powerfail-file (getenv "GUIX_APCUPSD_POWERFAIL_FILE"))
-
-       (define (err . args)
-         (apply format (current-error-port) args))
-       (define (wall . args)
-         (system* #$(file-append util-linux "/bin/wall") (apply format #f args)))
-       (define (apcupsd . args)
-         (apply system* #$(file-append apcupsd "/sbin/apcupsd") "-f" conf args))
-       (define (mail-to-root subject body)
-         (let ((port (open-pipe* OPEN_WRITE
-                                 "/run/privileged/bin/sendmail"
-                                 "-F" "apcupsd"
-                                 "root")))
-           (format port "Subject: ~a~%~%~a~&" subject body)
-           (close-pipe port)))
-       (match (cdr (command-line))
-         (((? string? cmd) name connected powered)
-          (let ((connected? (match connected
+  (define event-handlers (apcupsd-configuration-event-handlers config))
+  (match-record event-handlers <apcupsd-event-handlers>
+                ( modules killpower commfailure commok powerout
+                  onbattery offbattery ...)
+    (program-file
+     "apccontrol"
+     #~(begin
+         (use-modules (ice-9 format)
+                      (ice-9 match)
+                      (ice-9 popen)
+                      (srfi srfi-9)
+                      #$@modules)
+         ;; Script dir depends on these, and the configuration depends on the
+         ;; script dir.  To sever the cyclic dependency, pass the file names via
+         ;; environment variables.
+         (define conf (getenv "GUIX_APCUPSD_CONF"))
+         (define powerfail-file (getenv "GUIX_APCUPSD_POWERFAIL_FILE"))
+
+         (define (err . args)
+           (apply format (current-error-port) args))
+
+         (define (wall . args)
+           (system* #$(file-append util-linux "/bin/wall") (apply format #f args)))
+
+         (define (apcupsd . args)
+           (apply system* #$(file-append apcupsd "/sbin/apcupsd") "-f" conf args))
+
+         (define (mail-to-root subject body)
+           (let ((port (open-pipe* OPEN_WRITE
+                                   "/run/privileged/bin/sendmail"
+                                   "-F" "apcupsd"
+                                   "root")))
+             (format port "Subject: ~a~%~%~a~&" subject body)
+             (close-pipe port)))
+         
+         (match (cdr (command-line))
+           (((? string? cmd) name connected powered)
+            (let ((connected? (match connected
+                                ("1" #t)
+                                ("0" #f)))
+                  (powered? (match powered
                               ("1" #t)
-                              ("0" #f)))
-                (powered? (match powered
-                            ("1" #t)
-                            ("0" #f))))
-            (match cmd
-              ;; I am sure this could be done by macro, but meh.  Last release
-              ;; of apcupsd was in 2016, so maintaining this will not be much
-              ;; work.
-              ("killpower"
-               #$@(apcupsd-event-handlers-killpower
-                   (apcupsd-configuration-event-handlers config)))
-              ("commfailure"
-               #$@(apcupsd-event-handlers-commfailure
-                   (apcupsd-configuration-event-handlers config)))
-              ("commok"
-               #$@(apcupsd-event-handlers-commok
-                   (apcupsd-configuration-event-handlers config)))
-	      ("powerout"
-	       #$@(apcupsd-event-handlers-powerout
-		   (apcupsd-configuration-event-handlers config)))
-	      ("onbattery"
-	       #$@(apcupsd-event-handlers-onbattery
-		   (apcupsd-configuration-event-handlers config)))
-	      ("offbattery"
-	       #$@(apcupsd-event-handlers-offbattery
-		   (apcupsd-configuration-event-handlers config)))
-	      ("mainsback"
-	       #$@(apcupsd-event-handlers-mainsback
-		   (apcupsd-configuration-event-handlers config)))
-	      ("failing"
-	       #$@(apcupsd-event-handlers-failing
-		   (apcupsd-configuration-event-handlers config)))
-	      ("timeout"
-	       #$@(apcupsd-event-handlers-timeout
-		   (apcupsd-configuration-event-handlers config)))
-	      ("loadlimit"
-	       #$@(apcupsd-event-handlers-loadlimit
-		   (apcupsd-configuration-event-handlers config)))
-	      ("runlimit"
-	       #$@(apcupsd-event-handlers-runlimit
-		   (apcupsd-configuration-event-handlers config)))
-	      ("doreboot"
-	       #$@(apcupsd-event-handlers-doreboot
-		   (apcupsd-configuration-event-handlers config)))
-	      ("doshutdown"
-	       #$@(apcupsd-event-handlers-doshutdown
-		   (apcupsd-configuration-event-handlers config)))
-	      ("annoyme"
-	       #$@(apcupsd-event-handlers-annoyme
-		   (apcupsd-configuration-event-handlers config)))
-	      ("emergency"
-	       #$@(apcupsd-event-handlers-emergency
-		   (apcupsd-configuration-event-handlers config)))
-	      ("changeme"
-	       #$@(apcupsd-event-handlers-changeme
-		   (apcupsd-configuration-event-handlers config)))
-	      ("remotedown"
-	       #$@(apcupsd-event-handlers-remotedown
-		   (apcupsd-configuration-event-handlers config)))
-	      ("startselftest"
-	       #$@(apcupsd-event-handlers-startselftest
-		   (apcupsd-configuration-event-handlers config)))
-	      ("endselftest"
-	       #$@(apcupsd-event-handlers-endselftest
-		   (apcupsd-configuration-event-handlers config)))
-	      ("battdetach"
-	       #$@(apcupsd-event-handlers-battdetach
-		   (apcupsd-configuration-event-handlers config)))
-	      ("battattach"
-	       #$@(apcupsd-event-handlers-battattach
-		   (apcupsd-configuration-event-handlers config)))
-              (_
-               (err "Unknown event: ~a~%" cmd)
-               (err "Iff the event was emitted by apcupsd, this is a bug.~%")
-               (err "Please report to bug-guix@gnu.org.~%")
-               (exit #f)))))
-         (args
-          (err "Unknown arguments: ~a~%" args)
-          (err "Iff the arguments were passed by apcupsd, this is a bug.~%")
-          (err "Please report to bug-guix@gnu.org.~%")
-          (exit #f))))))
+                              ("0" #f))))
+              (match cmd
+                ("killpower" #$killpower)
+                ("commfailure" #$commfailure)
+                ("commok" #$commok)
+	        ("powerout" #$powerout)
+	        ("onbattery" #$onbattery)
+	        ("offbattery" #$offbattery)
+                [...]
+                (_
+                 (err "Unknown event: ~a~%" cmd)
+                 (err "If the event was emitted by apcupsd, this is a bug.~%")
+                 (err "Please report to bug-guix@gnu.org.~%")
+                 (exit #f)))))
+           (args
+            (err "Unknown arguments: ~a~%" args)
+            (err "If the arguments were passed by apcupsd, this is a bug.~%")
+            (err "Please report to bug-guix@gnu.org.~%")
+            (exit #f))))))))
 
 (define (apcupsd-script-dir config)
   (computed-file
--8<---------------cut here---------------end--------------->8---

[...]

>>> This file header is taken from the official configuration file
>>> distributed with the apcupsd (except the GNU Guix part).  So while I do
>>> expect that this configuration file should work with newer version, the
>>> upstream decided to put the version into the configuration file.
>>>
>>> I have no strong opinion either way here, should I just remove the file
>>> header completely?
>>
>> I think so, since we're going the path of producing our own, we don't
>> need to keep things that are not deemed useful.
>
> I have removed the version, but kept the header, so that there is
> reference to apcupsd-service-type left in the file.

Sounds reasonable.

[...]

> Getting bit off topic, but I am not sure how that would work.  Between
> various macros, and Scheme being LISP-1, I have no idea how to write
> robust code that would just magically always indent "right".
>
> But I would be glad to be proven wrong. :)

I guess you could have a procedure that calls the existing indenting
Elisp functions, and then have a post-processing pass on top to fix it
the way wa want.  It's probably a bit over the top :-).  I like
your/Emacs' down to Earth solution.

[...]

> One additional change I have made is to change
>
>         (requirement '())
>
>
> into
>
>         (requirement '(user-processes))
>
> Without the dependency, the daemon got respawned by shepherd on shutdown
> and prevented the machine from going offline, which sucked a bit. ^_^

Oh wow; good catch.  That seems a rather large foot gun to have for
service writers.  I wonder if something could be done about it in the
Shepherd.

> I thought I would mention it so that you can keep it in mind for future
> code reviews.

Indeed, thanks for bringing this to my attention.

> With that I think I am out of things that I want to change or would
> appreciate feedback on, so I am sending a v2.  Thank you for working
> with me through this, the code is much better than in v1.

I'll let you work through my last match-record suggestion above, if you
want and send a v3.

I'm also attaching a fixup with the terminology changes I've submitted
upstream if you'd like to validate it still works (I don't have any
UPS to try it with myself).
Thank you for your patience!
  

Comments

Tomas Volf Feb. 23, 2025, 9:21 p.m. UTC | #1
Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:

> [..]

>>> I just thought about it, perhaps it could be more concise to extract the
>>> field values using match-record (these are bound to shorter names, since
>>> they omit the 'apcupsd-configuration-' prefix).
>>
>> If I got the idea right, you suggest converting
>>
>> 	      ("emergency"
>> 	       #$@(apcupsd-event-handlers-emergency
>> 		   (apcupsd-configuration-event-handlers cfg)))
>>
>>
>> into
>>
>> 	      ("emergency"
>> 	       #$@(match-record cfg <apcupsd-configuration> (handlers)
>>                     (match-record handlers <apcupsd-event-handlers> (emergency)
>>                       emergency)))
>>
>>
>> I am not sure it is increase in readability, but maybe I misunderstood
>> the suggestion.
>
> I think something like this should work:
>
> modified   gnu/services/power.scm
> @@ -494,119 +494,67 @@ (define-configuration apcupsd-configuration
>     empty-serializer))
>  
>  (define (%apccontrol config)
> -  (program-file
> -   "apccontrol"
> -   #~(begin
> -       (use-modules (ice-9 format)
> -                    (ice-9 match)
> -                    (ice-9 popen)
> -                    (srfi srfi-9)
> -                    #$@(apcupsd-event-handlers-modules
> -                        (apcupsd-configuration-event-handlers config)))
> -       ;; Script dir depends on these, and the configuration depends on the
> -       ;; script dir.  To sever the cyclic dependency, pass the file names via
> -       ;; environment variables.
> -       (define conf (getenv "GUIX_APCUPSD_CONF"))
> -       (define powerfail-file (getenv "GUIX_APCUPSD_POWERFAIL_FILE"))
> -
> -       (define (err . args)
> -         (apply format (current-error-port) args))
> -       (define (wall . args)
> -         (system* #$(file-append util-linux "/bin/wall") (apply format #f args)))
> -       (define (apcupsd . args)
> -         (apply system* #$(file-append apcupsd "/sbin/apcupsd") "-f" conf args))
> -       (define (mail-to-root subject body)
> -         (let ((port (open-pipe* OPEN_WRITE
> -                                 "/run/privileged/bin/sendmail"
> -                                 "-F" "apcupsd"
> -                                 "root")))
> -           (format port "Subject: ~a~%~%~a~&" subject body)
> -           (close-pipe port)))
> -       (match (cdr (command-line))
> -         (((? string? cmd) name connected powered)
> -          (let ((connected? (match connected
> +  (define event-handlers (apcupsd-configuration-event-handlers config))
> +  (match-record event-handlers <apcupsd-event-handlers>
> +                ( modules killpower commfailure commok powerout
> +                  onbattery offbattery ...)
> +    (program-file
> +     "apccontrol"
> +     #~(begin
> +         (use-modules (ice-9 format)
> +                      (ice-9 match)
> +                      (ice-9 popen)
> +                      (srfi srfi-9)
> +                      #$@modules)
> +         ;; Script dir depends on these, and the configuration depends on the
> +         ;; script dir.  To sever the cyclic dependency, pass the file names via
> +         ;; environment variables.
> +         (define conf (getenv "GUIX_APCUPSD_CONF"))
> +         (define powerfail-file (getenv "GUIX_APCUPSD_POWERFAIL_FILE"))
> +
> +         (define (err . args)
> +           (apply format (current-error-port) args))
> +
> +         (define (wall . args)
> +           (system* #$(file-append util-linux "/bin/wall") (apply format #f args)))
> +
> +         (define (apcupsd . args)
> +           (apply system* #$(file-append apcupsd "/sbin/apcupsd") "-f" conf args))
> +
> +         (define (mail-to-root subject body)
> +           (let ((port (open-pipe* OPEN_WRITE
> +                                   "/run/privileged/bin/sendmail"
> +                                   "-F" "apcupsd"
> +                                   "root")))
> +             (format port "Subject: ~a~%~%~a~&" subject body)
> +             (close-pipe port)))
> +         
> +         (match (cdr (command-line))
> +           (((? string? cmd) name connected powered)
> +            (let ((connected? (match connected
> +                                ("1" #t)
> +                                ("0" #f)))
> +                  (powered? (match powered
>                                ("1" #t)
> -                              ("0" #f)))
> -                (powered? (match powered
> -                            ("1" #t)
> -                            ("0" #f))))
> -            (match cmd
> -              ;; I am sure this could be done by macro, but meh.  Last release
> -              ;; of apcupsd was in 2016, so maintaining this will not be much
> -              ;; work.
> -              ("killpower"
> -               #$@(apcupsd-event-handlers-killpower
> -                   (apcupsd-configuration-event-handlers config)))
> -              ("commfailure"
> -               #$@(apcupsd-event-handlers-commfailure
> -                   (apcupsd-configuration-event-handlers config)))
> -              ("commok"
> -               #$@(apcupsd-event-handlers-commok
> -                   (apcupsd-configuration-event-handlers config)))
> -	      ("powerout"
> -	       #$@(apcupsd-event-handlers-powerout
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("onbattery"
> -	       #$@(apcupsd-event-handlers-onbattery
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("offbattery"
> -	       #$@(apcupsd-event-handlers-offbattery
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("mainsback"
> -	       #$@(apcupsd-event-handlers-mainsback
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("failing"
> -	       #$@(apcupsd-event-handlers-failing
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("timeout"
> -	       #$@(apcupsd-event-handlers-timeout
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("loadlimit"
> -	       #$@(apcupsd-event-handlers-loadlimit
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("runlimit"
> -	       #$@(apcupsd-event-handlers-runlimit
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("doreboot"
> -	       #$@(apcupsd-event-handlers-doreboot
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("doshutdown"
> -	       #$@(apcupsd-event-handlers-doshutdown
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("annoyme"
> -	       #$@(apcupsd-event-handlers-annoyme
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("emergency"
> -	       #$@(apcupsd-event-handlers-emergency
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("changeme"
> -	       #$@(apcupsd-event-handlers-changeme
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("remotedown"
> -	       #$@(apcupsd-event-handlers-remotedown
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("startselftest"
> -	       #$@(apcupsd-event-handlers-startselftest
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("endselftest"
> -	       #$@(apcupsd-event-handlers-endselftest
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("battdetach"
> -	       #$@(apcupsd-event-handlers-battdetach
> -		   (apcupsd-configuration-event-handlers config)))
> -	      ("battattach"
> -	       #$@(apcupsd-event-handlers-battattach
> -		   (apcupsd-configuration-event-handlers config)))
> -              (_
> -               (err "Unknown event: ~a~%" cmd)
> -               (err "Iff the event was emitted by apcupsd, this is a bug.~%")
> -               (err "Please report to bug-guix@gnu.org.~%")
> -               (exit #f)))))
> -         (args
> -          (err "Unknown arguments: ~a~%" args)
> -          (err "Iff the arguments were passed by apcupsd, this is a bug.~%")
> -          (err "Please report to bug-guix@gnu.org.~%")
> -          (exit #f))))))
> +                              ("0" #f))))
> +              (match cmd
> +                ("killpower" #$killpower)
> +                ("commfailure" #$commfailure)
> +                ("commok" #$commok)
> +	        ("powerout" #$powerout)
> +	        ("onbattery" #$onbattery)
> +	        ("offbattery" #$offbattery)
> +                [...]
> +                (_
> +                 (err "Unknown event: ~a~%" cmd)
> +                 (err "If the event was emitted by apcupsd, this is a bug.~%")
> +                 (err "Please report to bug-guix@gnu.org.~%")
> +                 (exit #f)))))
> +           (args
> +            (err "Unknown arguments: ~a~%" args)
> +            (err "If the arguments were passed by apcupsd, this is a bug.~%")
> +            (err "Please report to bug-guix@gnu.org.~%")
> +            (exit #f))))))))
>  
>  (define (apcupsd-script-dir config)
>    (computed-file
>
> [...]

I get the idea now, thank you.  Yes, that is *much* nicer.  Updated.

> [..]
> I'll let you work through my last match-record suggestion above, if you
> want and send a v3.

Incorporated and v3 sent.  This time a single patch, since the package
was already merged.

>
> I'm also attaching a fixup with the terminology changes I've submitted
> upstream if you'd like to validate it still works (I don't have any
> UPS to try it with myself).

Thank you, but I will pass on that.  I respect your choice to invest
time into this effort, but for me this issue it not high enough on my
priority list to do the same.

Have a nice day,
Tomas
  

Patch

From 63457572d4b84ba17ef34ab479fd0e425f7ca774 Mon Sep 17 00:00:00 2001
Message-ID: <63457572d4b84ba17ef34ab479fd0e425f7ca774.1739861410.git.maxim.cournoyer@gmail.com>
From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Date: Tue, 18 Feb 2025 09:46:45 +0900
Subject: [PATCH] fixup! services: Add power.

---
 doc/guix.texi                                 |    2 +-
 gnu/local.mk                                  |    1 +
 .../patches/apcupsd-leader-follower.patch     | 1847 +++++++++++++++++
 gnu/packages/power.scm                        |    4 +-
 gnu/services/power.scm                        |    4 +-
 5 files changed, 1854 insertions(+), 4 deletions(-)
 create mode 100644 gnu/packages/patches/apcupsd-leader-follower.patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 126e542122..06f51fa3f9 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -36789,7 +36789,7 @@  Power Management Services
 @item connected?
 Is @code{#t} if @command{apcupsd} is connected to the UPS via a serial
 port (or a USB port).  In most configurations, this will be the case.
-In the case of a Slave machine where apcupsd is not directly connected
+In the case of a follower machine where apcupsd is not directly connected
 to the UPS, this value will be @code{#f}.
 
 @item powered?
diff --git a/gnu/local.mk b/gnu/local.mk
index 8042ba0482..d1e7af3743 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -990,6 +990,7 @@  dist_patch_DATA =						\
   %D%/packages/patches/antlr3-3_1-fix-java8-compilation.patch	\
   %D%/packages/patches/antlr3-3_3-fix-java8-compilation.patch	\
   %D%/packages/patches/aoflagger-use-system-provided-pybind11.patch \
+  %D%/packages/patches/apcupsd-leader-follower.patch		\
   %D%/packages/patches/apr-fix-atomics.patch			\
   %D%/packages/patches/apr-skip-getservbyname-test.patch	\
   %D%/packages/patches/aria2-unbundle-wslay.patch		\
diff --git a/gnu/packages/patches/apcupsd-leader-follower.patch b/gnu/packages/patches/apcupsd-leader-follower.patch
new file mode 100644
index 0000000000..632b6ede71
--- /dev/null
+++ b/gnu/packages/patches/apcupsd-leader-follower.patch
@@ -0,0 +1,1847 @@ 
+This replaces the master/slave termininology with leader/follower, which
+is more inclusive and forward-looking.
+
+Index: ReleaseNotes
+===================================================================
+--- ReleaseNotes	(revision 2381)
++++ ReleaseNotes	(working copy)
+@@ -5,10 +5,15 @@
+ new features over the previous 3.12.x stable series. Users of all previous
+ versions are encouraged to upgrade.
+ 
+-IF YOU USE THE OLD STYLE MASTER/SLAVE NETWORKING MODE, BE SURE TO READ THE
++IF YOU USE THE OLD STYLE LEADER/FOLLOWER NETWORKING MODE, BE SURE TO READ THE
+ 3.14.0 RELEASE NOTES BELOW.
+ 
++3.15.0 -- TBD
+ 
++VARIA
++
++  * Replace master/slave terminology with leader/follower throughout project
++
+ 3.14.14 -- 31 May 2016
+ 
+ BUG FIXES
+Index: autoconf/configure.in
+===================================================================
+--- autoconf/configure.in	(revision 2381)
++++ autoconf/configure.in	(working copy)
+@@ -600,8 +600,8 @@
+     [])
+ 
+ AC_ARG_ENABLE(net, [
+-AC_HELP_STRING([--enable-net], [Compile networking driver for slaves (default)])
+-AC_HELP_STRING([--disable-net], [No network driver for slaves])],
++AC_HELP_STRING([--enable-net], [Compile networking driver for followers (default)])
++AC_HELP_STRING([--disable-net], [No network driver for followers])],
+    [ if test "$enableval" = "yes" ; then
+         AC_DEFINE(HAVE_NET_DRIVER,, [Define if building net driver])
+         NET_DRIVER="net"
+Index: configure
+===================================================================
+--- configure	(revision 2381)
++++ configure	(working copy)
+@@ -1477,8 +1477,8 @@
+   --enable-usb            Compile USB UPS code
+   --disable-usb           No USB UPS code (default)
+ 
+-  --enable-net            Compile networking driver for slaves (default)
+-  --disable-net           No network driver for slaves
++  --enable-net            Compile networking driver for followers (default)
++  --disable-net           No network driver for followers
+ 
+   --enable-snmp           Compile SNMP driver (default)
+   --disable-snmp          No SNMP driver
+Index: doc/apcaccess.8
+===================================================================
+--- doc/apcaccess.8	(revision 2381)
++++ doc/apcaccess.8	(working copy)
+@@ -92,7 +92,7 @@
+ : Date and time apcupsd was started
+ .It STATUS
+ : UPS status.  One or more of the following (space-separated):
+-CAL TRIM BOOST ONLINE ONBATT OVERLOAD LOWBATT REPLACEBATT NOBATT SLAVE SLAVEDOWN
++CAL TRIM BOOST ONLINE ONBATT OVERLOAD LOWBATT REPLACEBATT NOBATT FOLLOWER FOLLOWERDOWN
+ .br
+ or
+ .br
+@@ -101,8 +101,8 @@
+ or
+ .br
+ SHUTTING DOWN
+-.It MASTERUPD
+-: Last time the master sent an update to the slave
++.It LEADERUPD
++: Last time the leader sent an update to the follower
+ .It ENDAPC
+ : Date and time of status information was written
+ .El
+Index: doc/apccontrol.8
+===================================================================
+--- doc/apccontrol.8	(revision 2381)
++++ doc/apccontrol.8	(working copy)
+@@ -34,7 +34,7 @@
+ configuration file - not the name in the EEPROM of a smart UPS. 
+ .It connected
+ This is 1 if apcupsd is connected to the UPS via a serial or USB port. 
+-In the case of a slave machine where apcupsd is not directly connected 
++In the case of a follower machine where apcupsd is not directly connected 
+ to the UPS, this value will be 0.
+ .It powered
+ This is 1 if the computer on which apcupsd is running is powered by the UPS 
+@@ -164,9 +164,9 @@
+ .Pp
+ Default action -- does nothing.
+ .It remotedown
+-apcupsd generates this event on a slave machine when it detects either (1)
+-that the master has shutdown, or (2) that an onbattery event has occurred 
+-and communication with the master has been lost.
++apcupsd generates this event on a follower machine when it detects either (1)
++that the leader has shutdown, or (2) that an onbattery event has occurred 
++and communication with the leader has been lost.
+ .Pp
+ Default action: sends "Remote Shutdown. Beginning Shutdown Sequence." to wall and exits. Immediately after this, apcupsd generates a doshutdown event to 
+ shutdown the system.
+Index: doc/apcupsd.conf.5
+===================================================================
+--- doc/apcupsd.conf.5	(revision 2381)
++++ doc/apcupsd.conf.5	(working copy)
+@@ -286,7 +286,7 @@
+ .Ss SHARE-UPS CONFIGURATION DIRECTIVES
+ .Pp
+ .Bl -hang -width "xxxxxxx"
+-.It UPSCLASS [\& standalone | shareslave | sharemaster \&]
++.It UPSCLASS [\& standalone | sharefollower | shareleader \&]
+ .Pp
+ The default is "standalone" and should be used for 
+ all computers powered by the UPS,  with a direct connection to 
+@@ -293,10 +293,10 @@
+ the UPS and where there are no other computers dependent on power 
+ from the UPS. This is the "normal" case.
+ .Pp
+-Use "shareslave" if you are using a Share-UPS interface expander 
++Use "sharefollower" if you are using a Share-UPS interface expander 
+ and connected to the BASIC port (simple signalling). 
+ .Pp
+-Use "sharemaster", if you are using a Share-UPS interface
++Use "shareleader", if you are using a Share-UPS interface
+ expander and connected to the ADVANCED port (smart signalling). 
+ .Pp
+ .It UPSMODE [\& disable | share \&]
+Index: doc/manual/manual.rst
+===================================================================
+--- doc/manual/manual.rst	(revision 2381)
++++ doc/manual/manual.rst	(working copy)
+@@ -80,7 +80,7 @@
+ serial-line UPS, you'll have to read about serial installation (see
+ `Installation: Serial-Line UPSes`_). If you need more
+ details about administration for unusual situations (such as a
+-master/slave or multi-UPS setup) you'll need to read the sections on
++leader/follower or multi-UPS setup) you'll need to read the sections on
+ those topics as well. Finally,
+ there are a number of technical reference sections which 
+ gives full details on things like configuration file directives and 
+@@ -262,9 +262,9 @@
+ 
+ net
+     This is the keyword to specify if you are using your
+-    UPS in Slave mode (i.e. the machine is not directly connected to
++    UPS in Follower mode (i.e. the machine is not directly connected to
+     the UPS, but to another machine which is), and it is connected to
+-    the Master via an ethernet connection. You must have apcupsd's
++    the Leader via an ethernet connection. You must have apcupsd's
+     Network Information Services NIS turned on for this mode to work.
+ 
+ snmp
+@@ -1229,12 +1229,12 @@
+ your halt script should things go wrong. Please consult the
+ specific system dependent README files for more details.
+ 
+-Please note that if you install from RPMs for a slave machine, you
++Please note that if you install from RPMs for a follower machine, you
+ will need to remove the changes that the RPM install script made
+ (similar to what is noted above) to the halt script. This is
+-because on a slave machine there is no connection to the UPS, so
++because on a follower machine there is no connection to the UPS, so
+ there is no need to attempt to power off the UPS. That will be done
+-by the master.
++by the leader.
+ 
+ 
+ Configure Options
+@@ -1280,9 +1280,9 @@
+ --enable-dumb  Turns on generation of the dumb signalling driver code (default).
+ --enable-usb   Turns on generation of the USB driver code. By default this is disabled.
+ --enable-net  Turns on generation of the NIS
+-    network driver for slaves. For each slave, this is the only driver
++    network driver for followers. For each follower, this is the only driver
+     needed. This driver works by reading the information from the the
+-    configured master using the NIS (Network Information Services)
++    configured leader using the NIS (Network Information Services)
+     interface.
+ --enable-snmp  Turns on generation of the
+     SNMP driver. This driver accesses the UPS over the network using
+@@ -1346,7 +1346,7 @@
+     checking is done on the value entered, so you must ensure that it
+     is a valid IP address.
+ --with-net-port=port  This option allows
+-    you to specify what port apcupsd will use for Master and Slave
++    you to specify what port apcupsd will use for Leader and Follower
+     communications. The default is system dependent but usually 6666.
+     This option simply sets the appropriate port in the apcupsd.conf
+     file, which can be changed at any later time.
+@@ -2046,22 +2046,22 @@
+ change in state of the NIS server before the server has shutdown.
+ Normally, you have at least 30 seconds of grace time between the
+ time the NIS server decides to shutdown and the time it no longer
+-responds. Your slave must poll during this interval.
++responds. Your follower must poll during this interval.
+ 
+ Any client run using the Net driver will shutdown when its own
+ timers expire or when the NIS server shuts down, whichever occurs
+-first. This means that if you want the slave to shutdown before the
++first. This means that if you want the follower to shutdown before the
+ server, you need only set ``BATTERYLEVEL``, ``MINUTES`` or
+ ``TIMEOUT`` on the client for a faster shutdown than the values
+-defined on the NIS server. This can often be useful if the slave is
+-less important than the master and you wish to reduce battery power
+-consumption so that the master can remain up longer during a power
++defined on the NIS server. This can often be useful if the follower is
++less important than the leader and you wish to reduce battery power
++consumption so that the leader can remain up longer during a power
+ outage.
+ 
+ NIS clients work principally by reading the STATFLAG record that is
+ sent by the NIS server (present in the output of apcaccess). The
+ low 16 bits are the standard APC status flag, and the upper 16 bits
+-represent the internal state of apcupsd, so the slave can see when
++represent the internal state of apcupsd, so the follower can see when
+ the power fails and know when to shutdown.
+ 
+ It would be possible to have a client also work as a server, but
+@@ -2069,23 +2069,23 @@
+ to the secondary client.
+ 
+ 
+-Differences between NIS Client/Server and the old (now removed) Master/Slave modes
+-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Differences between NIS Client/Server and the old (now removed) Leader/Follower modes
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 
+-The difference between the NIS mode and the removed master/slave
++The difference between the NIS mode and the removed leader/follower
+ mode is that the NIS server has no explicit knowledge of the
+-slaves. The NIS server makes its information available via the net
+-(NIS), and the NIS slaves read it. When the NIS server is going to
+-shutdown, it makes the information available to any NIS slave that
++followers. The NIS server makes its information available via the net
++(NIS), and the NIS followers read it. When the NIS server is going to
++shutdown, it makes the information available to any NIS follower that
+ polls it, but the NIS server does not explicitly call each NIS
+-slave as is the case in the Master/Slave networking described
++follower as is the case in the Leader/Follower networking described
+ several sections above.
+ 
+-Think of the difference as push (Master/Slave) vs. pull
+-(NIS-based). In the case of M/S, the master makes all the shutdown
+-decisions and notifies the slaves when they are to shut down or
+-when some other interesting event happens. The slaves just do
+-whatever the master says, whenever the master says to. On the other
++Think of the difference as push (Leader/Follower) vs. pull
++(NIS-based). In the case of M/S, the leader makes all the shutdown
++decisions and notifies the followers when they are to shut down or
++when some other interesting event happens. The followers just do
++whatever the leader says, whenever the leader says to. On the other
+ hand, with the NIS-based network config you basically "publish" the
+ UPS status from one server and then your clients view that status
+ and make their own decisions.
+@@ -3138,7 +3138,7 @@
+ ensure that the clients can reach it by opening up ``NISPORT``
+ (default: TCP 3551) on any firewall running on the server. You may
+ wish to configure your firewall(s) to *only* allow connections from
+-your local network or specifically from the masters, slaves, and
++your local network or specifically from the leaders, followers, and
+ servers as needed.
+ 
+ 
+@@ -3319,12 +3319,12 @@
+     device.
+ 
+ :Question:
+-    How do I ensure that the slaves shutdown before the master?
++    How do I ensure that the followers shutdown before the leader?
+ :Answer:
+-    Slaves make their shutdown decision independently from the master.
++    Followers make their shutdown decision independently from the leader.
+     Therefore you can use the ``TIMEOUT``, ``MINUTES``, and ``BATTERYLEVEL``
+-    settings in the slaves' apcupsd.conf to configure them to shut down 
+-    before the master.
++    settings in the followers' apcupsd.conf to configure them to shut down 
++    before the leader.
+     
+ :Question:
+     How do I ensure that my database server is correctly shutdown?
+@@ -3408,7 +3408,7 @@
+ *connected*
+     is 1 if apcupsd is connected to the UPS
+     via a serial port (or a USB port). In most configurations, this
+-    will be the case. In the case of a Slave machine where apcupsd is
++    will be the case. In the case of a Follower machine where apcupsd is
+     not directly connected to the UPS, this value will be 0.
+ 
+ *powered*
+@@ -3513,8 +3513,8 @@
+     *Default:* nothing
+ 
+ **remotedown**
+-    This event is generated on a slave
+-    machine when it detects either that the master has shutdown, or
++    This event is generated on a follower
++    machine when it detects either that the leader has shutdown, or
+     that a onbattery situation exists and the communications line has
+     been severed.
+ 
+@@ -3991,7 +3991,7 @@
+   attempt to autotedect by trying "private" and "public".
+   (optional, default: autodetect).
+ 
+-A NIS Server/Client (Master/Slave) configuration 
++A NIS Server/Client (Leader/Follower) configuration 
+ with multiple servers is still applicable. However, an alternative 
+ configuration is possible with an SNMP
+ enabled UPS. In this arrangement, all connected servers will be
+@@ -4418,8 +4418,8 @@
+ On some Windows systems, the
+ domain resolution does not seem to work if you have not configured
+ a DNS server in the Network section of the Control Panel. This
+-problem should be apparent only when running a slave configuration.
+-In this case, when you specify the name of the master in your
++problem should be apparent only when running a follower configuration.
++In this case, when you specify the name of the leader in your
+ apcupsd.conf file, apcupsd will be unable to resolve the name to a
+ valid IP address. To circumvent this problem, simply enter the
+ address as an IP address rather than a hostname, or alternatively,
+@@ -5022,7 +5022,7 @@
+     do not provide a battery exhausted signal (only testing can
+     determine this point). For more information, see the 
+     `Testing Apcupsd`_ section of this manual. This
+-    timer can also be useful if you want some slave machines to
++    timer can also be useful if you want some follower machines to
+     shutdown before other machines to conserve battery power. It is
+     also useful for testing apcupsd because you can force a rapid
+     shutdown by setting a small value (e.g. 60) and pulling the plug to
+@@ -5195,17 +5195,17 @@
+ The following directives apply to sharing an UPS using a ShareUPS 
+ hardware module. Most users will not use this mode.
+ 
+-**UPSCLASS** *standalone* | *shareslave* | *sharemaster*
++**UPSCLASS** *standalone* | *sharefollower* | *shareleader*
+ 
+     The default is ``standalone`` and should be used for all machines
+     powered by the UPS and having a serial port or other direct
+     connection to the UPS. This is the normal case.
+ 
+-    Use ``shareslave`` if and only if you are using a ShareUPS and
++    Use ``sharefollower`` if and only if you are using a ShareUPS and
+     connected to a BASIC Port with Simple Signal. This code is not
+     fully tested.
+ 
+-    Use ``sharemaster``, if and only if you are using a ShareUPS and
++    Use ``shareleader``, if and only if you are using a ShareUPS and
+     connected to the ADVANCED Port Smart Signal control. This code is
+     not fully tested.
+ 
+@@ -5782,19 +5782,19 @@
+ automatically reboot. In any case, your machine should have been
+ cleanly shut down.
+ 
+-Master/Slave Shutdown
+----------------------
++Leader/Follower Shutdown
++------------------------
+ 
+-In master/slave configurations, however, the master cannot be 100
+-percent sure that the slaves have all shutdown before it performs
++In leader/follower configurations, however, the leader cannot be 100
++percent sure that the followers have all shutdown before it performs
+ the power off. To avoid this situation, be sure to configure any
+-slaves (clients) to shut down before the master by setting different
++followers (clients) to shut down before the leader by setting different
+ ``TIMEOUT``, ``BATTERYLEVEL``, or ``MINUTES`` parameters in the 
+ config file.
+ 
+-Also, on a slave machine, you do not want to use the modified halt
++Also, on a follower machine, you do not want to use the modified halt
+ script since it will recall apcupsd, which will detect that it is a
+-slave (i.e. no connection to the UPS) and will complain that it
++follower (i.e. no connection to the UPS) and will complain that it
+ cannot do the killpower. This situation is not harmful just
+ annoying and possibly confusing.
+ 
+Index: examples/Makefile
+===================================================================
+--- examples/Makefile	(revision 2381)
++++ examples/Makefile	(working copy)
+@@ -3,12 +3,12 @@
+ SUBDIRS = 
+ include $(topdir)/autoconf/targets.mak
+ 
+-TARGETS = hid-ups hid-set client megaclient newslave upsapm \
++TARGETS = hid-ups hid-set client megaclient newfollower upsapm \
+           smartsim snoopdecode
+ 
+ SRCS = $(foreach target,$(TARGETS),$(target).c)
+ 
+-all-targets: client megaclient newslave upsapm smartsim snoopdecode
++all-targets: client megaclient newfollower upsapm smartsim snoopdecode
+ 
+ $(TARGETS): %: $(call SRC2OBJ,%.c) $(APCLIBS)
+ 	$(LINK)
+Index: examples/nagios_plugin_check_apcupsd.c
+===================================================================
+--- examples/nagios_plugin_check_apcupsd.c	(revision 2381)
++++ examples/nagios_plugin_check_apcupsd.c	(working copy)
+@@ -202,8 +202,8 @@
+       retVal = NAGIOS_OK;
+       strcpy(sStatus, S_NAGIOS_OK);
+    }
+-   if (iStatus & UPS_slave) {
+-      strcat(status, "SLAVE ");
++   if (iStatus & UPS_follower) {
++      strcat(status, "FOLLOWER ");
+       retVal = NAGIOS_OK;
+       strcpy(sStatus, S_NAGIOS_OK);
+    }
+Index: examples/newfollower.c
+===================================================================
+--- examples/newfollower.c	(nonexistent)
++++ examples/newfollower.c	(working copy)
+@@ -0,0 +1,251 @@
++/*
++ * Client test program for apcnisd to be used
++ * as a base for the new leader/follower code.
++ *
++ * Build it with: cc newfollower.c ../lib/libapc.a -o newclient
++ *
++ * Execute: ./newfollower [host[:port]]
++ *
++ * The two commands currently (Apr 2001) accepted by the
++ * server are "status" and "events".
++ *
++ */
++
++#include "apc.h"
++
++#ifdef HAVE_NISLIB
++
++/* Default values, can be changed on command line */
++#define SERV_TCP_PORT 3551
++#define SERV_HOST_ADDR "127.0.0.1"
++
++#define BIGBUF 4096
++char statbuf[BIGBUF];
++int statlen = BIGBUF;
++
++/* List of variables that can be read by getupsvar()
++ * First field is that name given to getupsvar(),
++ * Second field is our internal name as produced by the STATUS
++ *   output from apcupsd.
++ * Third field, if 0 returns everything to the end of the
++ *    line, and if 1 returns only to first space (e.g. integers,
++ *    and floating point values.
++ */
++static struct {
++   const char *request;
++   const char *upskeyword;
++   int nfields;
++} cmdtrans[] = {
++   {"model",      "MODEL",    0},
++   {"upsmodel",   "UPSMODEL", 0},
++   {"date",       "DATE",     0},
++   {"battcap",    "BCHARGE",  1},
++   {"mbattchg",   "MBATTCHG", 1},
++   {"battvolt",   "BATTV",    1},
++   {"nombattv",   "NOMBATTV", 1},
++   {"utility",    "LINEV",    1},
++   {"upsload",    "LOADPCT",  1},
++   {"loadpct",    "LOADPCT",  1},
++   {"outputv",    "OUTPUTV",  1},
++   {"status",     "STATFLAG", 1},
++   {"linemin",    "MINLINEV", 1},
++   {"linemax",    "MAXLINEV", 1},
++   {"upstemp",    "ITEMP",    1},
++   {"outputfreq", "LINEFREQ", 1},
++   {"translo",    "LOTRANS",  1},
++   {"transhi",    "HITRANS",  1},
++   {"runtime",    "TIMELEFT", 1},
++   {"mintimel",   "MINTIMEL", 1},
++   {"retpct",     "RETPCT",   1},          /* min batt to turn on UPS */
++   {"sense",      "SENSE",    1},
++   {"hostname",   "HOSTNAME", 1},
++   {"battdate",   "BATTDATE", 1},
++   {"serialno",   "SERIALNO", 1},
++   {"lastxfer",   "LASTXFER", 0},          /* reason for last xfer to batteries */
++   {"selftest",   "SELFTEST", 1},          /* results of last self test */
++   {"laststest",  "LASTSTEST", 0},
++   {"version",    "VERSION",  1},
++   {"upsname",    "UPSNAME",  1},
++   {"lowbatt",    "DLOWBATT", 1},          /* low battery power off delay */
++   {"battpct",    "BCHARGE",  1},
++   {"highxfer",   "HITRANS",  1},
++   {"lowxfer",    "LOTRANS",  1},
++   {"cable",      "CABLE",    0},
++   {"firmware",   "FIRMWARE", 0},
++   {NULL, NULL}
++};
++
++int fetch_data(char *host, int port);
++int getupsvar(char *host, int port, const char *request, char *answer, int anslen);
++int fill_buffer(int sockfd);
++
++extern int net_errno;
++
++void error_abort(char *msg)
++{
++   fprintf(stderr, msg);
++   exit(1);
++}
++
++int main(int argc, char *argv[])
++{
++   int port;
++   char host[200];
++   char msg[200], *p;
++   char hostname[100];
++   char release[100];
++   char upsname[100];
++   char status[100];
++
++   strcpy(host, SERV_HOST_ADDR);
++   port = SERV_TCP_PORT;
++
++   if (argc > 1) {
++      strcpy(host, argv[1]); /* get host from command line */
++      p = strchr(host, ':');
++      if (p) {
++	 *p++ = 0;
++	 port = atoi(p);
++      }
++   }
++
++   if (getupsvar(host, port, "hostname", msg, sizeof(msg)) <= 0) {
++       printf("Error getting variable\n");
++       exit(1);
++   }
++   strcpy(hostname, msg);
++
++   if (getupsvar(host, port, "version", msg, sizeof(msg)) <= 0) {
++       printf("Error getting variable\n");
++       exit(1);
++   }
++   strcpy(release, msg);
++
++   if (getupsvar(host, port, "upsname", msg, sizeof(msg)) <= 0) {
++       printf("Error getting variable\n");
++       exit(1);
++   }
++   strcpy(upsname, msg);
++
++   if (getupsvar(host, port, "status", msg, sizeof(msg)) <= 0) {
++       printf("Error getting variable\n");
++       exit(1);
++   }
++   strcpy(status, msg);
++
++   printf("For host=%s ups=%s apcupsd version=%s, the Status=%s\n",
++       hostname, upsname, release, status);
++
++   exit(0);
++}
++
++
++/*
++ * Read data into memory buffer to be used by getupsvar()
++ * Returns 0 on error
++ * Returns 1 if data fetched
++ */
++int fetch_data(char *host, int port)
++{
++   int sockfd;
++   int stat;
++
++   if ((sockfd = net_open(host, NULL, port)) < 0) {
++      printf("fetch_data: tcp_open failed for %s port %d", host, port);
++      return 0;
++   }
++
++   stat = fill_buffer(sockfd);		     /* fill statbuf */
++   net_close(sockfd);
++   return stat;
++
++}
++
++/*
++ *
++ * Returns 1 if var found
++ *   answer has var
++ * Returns 0 if variable name not found
++ *   answer has "Not found" is variable name not found
++ *   answer may have "N/A" if the UPS does not support this
++ *	 feature
++ * Returns -1 if network problem
++ *   answer has "N/A" if host is not available or network error
++ */
++int getupsvar(char *host, int port, const char *request, char *answer, int anslen)
++{
++    int i;
++    const char *stat_match = NULL;
++    char *find;
++    int nfields = 0;
++
++    if (!fetch_data(host, port)) {
++        strcpy(answer, "N/A");
++	return -1;
++    }
++
++    for (i=0; cmdtrans[i].request; i++)
++	if (!(strcmp(cmdtrans[i].request, request))) {
++	     stat_match = cmdtrans[i].upskeyword;
++	     nfields = cmdtrans[i].nfields;
++	}
++
++    if (stat_match != NULL) {
++	if ((find=strstr(statbuf, stat_match)) != NULL) {
++	     if (nfields == 1)	/* get one field */
++                 sscanf (find, "%*s %*s %s", answer);
++	     else {		/* get everything to eol */
++		 i = 0;
++		 find += 11;  /* skip label */
++                 while (*find != '\n')
++		     answer[i++] = *find++;
++		 answer[i] = 0;
++	     }
++             if (strcmp(answer, "N/A") == 0)
++		 return 0;
++	     return 1;
++	}
++    }
++
++    strcpy(answer, "Not found");
++    return 0;
++}
++
++#define MAXLINE 512
++
++/* Fill buffer with data from UPS network daemon
++ * Returns 0 on error
++ * Returns 1 if OK
++ */
++int fill_buffer(int sockfd)
++{
++   int n, stat = 1;
++   char buf[1000];
++
++   statbuf[0] = 0;
++   statlen = 0;
++   if (net_send(sockfd, "status", 6) != 6) {
++      printf("fill_buffer: write error on socket\n");
++      return 0;
++   }
++
++   while ((n = net_recv(sockfd, buf, sizeof(buf)-1)) > 0) {
++      buf[n] = 0;
++      strcat(statbuf, buf);
++   }
++   if (n < 0)
++      stat = 0;
++
++   statlen = strlen(statbuf);
++   return stat;
++
++}
++
++#else /* HAVE_NISLIB */
++
++int main(int argc, char *argv[]) {
++    printf("Sorry, NIS code is not compiled in apcupsd.\n");
++    return 1;
++}
++
++#endif /* HAVE_NISLIB */
+Index: examples/newslave.c
+===================================================================
+--- examples/newslave.c	(revision 2381)
++++ examples/newslave.c	(nonexistent)
+@@ -1,251 +0,0 @@
+-/*
+- * Client test program for apcnisd to be used
+- * as a base for the new master/slave code.
+- *
+- * Build it with: cc newslave.c ../lib/libapc.a -o newclient
+- *
+- * Execute: ./newslave [host[:port]]
+- *
+- * The two commands currently (Apr 2001) accepted by the
+- * server are "status" and "events".
+- *
+- */
+-
+-#include "apc.h"
+-
+-#ifdef HAVE_NISLIB
+-
+-/* Default values, can be changed on command line */
+-#define SERV_TCP_PORT 3551
+-#define SERV_HOST_ADDR "127.0.0.1"
+-
+-#define BIGBUF 4096
+-char statbuf[BIGBUF];
+-int statlen = BIGBUF;
+-
+-/* List of variables that can be read by getupsvar()
+- * First field is that name given to getupsvar(),
+- * Second field is our internal name as produced by the STATUS
+- *   output from apcupsd.
+- * Third field, if 0 returns everything to the end of the
+- *    line, and if 1 returns only to first space (e.g. integers,
+- *    and floating point values.
+- */
+-static struct {
+-   const char *request;
+-   const char *upskeyword;
+-   int nfields;
+-} cmdtrans[] = {
+-   {"model",      "MODEL",    0},
+-   {"upsmodel",   "UPSMODEL", 0},
+-   {"date",       "DATE",     0},
+-   {"battcap",    "BCHARGE",  1},
+-   {"mbattchg",   "MBATTCHG", 1},
+-   {"battvolt",   "BATTV",    1},
+-   {"nombattv",   "NOMBATTV", 1},
+-   {"utility",    "LINEV",    1},
+-   {"upsload",    "LOADPCT",  1},
+-   {"loadpct",    "LOADPCT",  1},
+-   {"outputv",    "OUTPUTV",  1},
+-   {"status",     "STATFLAG", 1},
+-   {"linemin",    "MINLINEV", 1},
+-   {"linemax",    "MAXLINEV", 1},
+-   {"upstemp",    "ITEMP",    1},
+-   {"outputfreq", "LINEFREQ", 1},
+-   {"translo",    "LOTRANS",  1},
+-   {"transhi",    "HITRANS",  1},
+-   {"runtime",    "TIMELEFT", 1},
+-   {"mintimel",   "MINTIMEL", 1},
+-   {"retpct",     "RETPCT",   1},          /* min batt to turn on UPS */
+-   {"sense",      "SENSE",    1},
+-   {"hostname",   "HOSTNAME", 1},
+-   {"battdate",   "BATTDATE", 1},
+-   {"serialno",   "SERIALNO", 1},
+-   {"lastxfer",   "LASTXFER", 0},          /* reason for last xfer to batteries */
+-   {"selftest",   "SELFTEST", 1},          /* results of last self test */
+-   {"laststest",  "LASTSTEST", 0},
+-   {"version",    "VERSION",  1},
+-   {"upsname",    "UPSNAME",  1},
+-   {"lowbatt",    "DLOWBATT", 1},          /* low battery power off delay */
+-   {"battpct",    "BCHARGE",  1},
+-   {"highxfer",   "HITRANS",  1},
+-   {"lowxfer",    "LOTRANS",  1},
+-   {"cable",      "CABLE",    0},
+-   {"firmware",   "FIRMWARE", 0},
+-   {NULL, NULL}
+-};
+-
+-int fetch_data(char *host, int port);
+-int getupsvar(char *host, int port, const char *request, char *answer, int anslen);
+-int fill_buffer(int sockfd);
+-
+-extern int net_errno;
+-
+-void error_abort(char *msg)
+-{
+-   fprintf(stderr, msg);
+-   exit(1);
+-}
+-
+-int main(int argc, char *argv[])
+-{
+-   int port;
+-   char host[200];
+-   char msg[200], *p;
+-   char hostname[100];
+-   char release[100];
+-   char upsname[100];
+-   char status[100];
+-
+-   strcpy(host, SERV_HOST_ADDR);
+-   port = SERV_TCP_PORT;
+-
+-   if (argc > 1) {
+-      strcpy(host, argv[1]); /* get host from command line */
+-      p = strchr(host, ':');
+-      if (p) {
+-	 *p++ = 0;
+-	 port = atoi(p);
+-      }
+-   }
+-
+-   if (getupsvar(host, port, "hostname", msg, sizeof(msg)) <= 0) {
+-       printf("Error getting variable\n");
+-       exit(1);
+-   }
+-   strcpy(hostname, msg);
+-
+-   if (getupsvar(host, port, "version", msg, sizeof(msg)) <= 0) {
+-       printf("Error getting variable\n");
+-       exit(1);
+-   }
+-   strcpy(release, msg);
+-
+-   if (getupsvar(host, port, "upsname", msg, sizeof(msg)) <= 0) {
+-       printf("Error getting variable\n");
+-       exit(1);
+-   }
+-   strcpy(upsname, msg);
+-
+-   if (getupsvar(host, port, "status", msg, sizeof(msg)) <= 0) {
+-       printf("Error getting variable\n");
+-       exit(1);
+-   }
+-   strcpy(status, msg);
+-
+-   printf("For host=%s ups=%s apcupsd version=%s, the Status=%s\n",
+-       hostname, upsname, release, status);
+-
+-   exit(0);
+-}
+-
+-
+-/*
+- * Read data into memory buffer to be used by getupsvar()
+- * Returns 0 on error
+- * Returns 1 if data fetched
+- */
+-int fetch_data(char *host, int port)
+-{
+-   int sockfd;
+-   int stat;
+-
+-   if ((sockfd = net_open(host, NULL, port)) < 0) {
+-      printf("fetch_data: tcp_open failed for %s port %d", host, port);
+-      return 0;
+-   }
+-
+-   stat = fill_buffer(sockfd);		     /* fill statbuf */
+-   net_close(sockfd);
+-   return stat;
+-
+-}
+-
+-/*
+- *
+- * Returns 1 if var found
+- *   answer has var
+- * Returns 0 if variable name not found
+- *   answer has "Not found" is variable name not found
+- *   answer may have "N/A" if the UPS does not support this
+- *	 feature
+- * Returns -1 if network problem
+- *   answer has "N/A" if host is not available or network error
+- */
+-int getupsvar(char *host, int port, const char *request, char *answer, int anslen)
+-{
+-    int i;
+-    const char *stat_match = NULL;
+-    char *find;
+-    int nfields = 0;
+-
+-    if (!fetch_data(host, port)) {
+-        strcpy(answer, "N/A");
+-	return -1;
+-    }
+-
+-    for (i=0; cmdtrans[i].request; i++)
+-	if (!(strcmp(cmdtrans[i].request, request))) {
+-	     stat_match = cmdtrans[i].upskeyword;
+-	     nfields = cmdtrans[i].nfields;
+-	}
+-
+-    if (stat_match != NULL) {
+-	if ((find=strstr(statbuf, stat_match)) != NULL) {
+-	     if (nfields == 1)	/* get one field */
+-                 sscanf (find, "%*s %*s %s", answer);
+-	     else {		/* get everything to eol */
+-		 i = 0;
+-		 find += 11;  /* skip label */
+-                 while (*find != '\n')
+-		     answer[i++] = *find++;
+-		 answer[i] = 0;
+-	     }
+-             if (strcmp(answer, "N/A") == 0)
+-		 return 0;
+-	     return 1;
+-	}
+-    }
+-
+-    strcpy(answer, "Not found");
+-    return 0;
+-}
+-
+-#define MAXLINE 512
+-
+-/* Fill buffer with data from UPS network daemon
+- * Returns 0 on error
+- * Returns 1 if OK
+- */
+-int fill_buffer(int sockfd)
+-{
+-   int n, stat = 1;
+-   char buf[1000];
+-
+-   statbuf[0] = 0;
+-   statlen = 0;
+-   if (net_send(sockfd, "status", 6) != 6) {
+-      printf("fill_buffer: write error on socket\n");
+-      return 0;
+-   }
+-
+-   while ((n = net_recv(sockfd, buf, sizeof(buf)-1)) > 0) {
+-      buf[n] = 0;
+-      strcat(statbuf, buf);
+-   }
+-   if (n < 0)
+-      stat = 0;
+-
+-   statlen = strlen(statbuf);
+-   return stat;
+-
+-}
+-
+-#else /* HAVE_NISLIB */
+-
+-int main(int argc, char *argv[]) {
+-    printf("Sorry, NIS code is not compiled in apcupsd.\n");
+-    return 1;
+-}
+-
+-#endif /* HAVE_NISLIB */
+Index: examples/status/Back-UPS-Pro-1000.status
+===================================================================
+--- examples/status/Back-UPS-Pro-1000.status	(revision 2381)
++++ examples/status/Back-UPS-Pro-1000.status	(working copy)
+@@ -4,7 +4,7 @@
+ RELEASE  : 3.8.1-3
+ CABLE    : Custom Cable Smart
+ MODEL    : BACK-UPS PRO 1000
+-UPSMODE  : Net Master
++UPSMODE  : Net Leader
+ STARTTIME: Thu Mar 08 11:22:12 EST 2001
+ SHARE    : NetworkUPS
+ UPSNAME  : N/A
+Index: examples/status/JapaneseUPS.status
+===================================================================
+--- examples/status/JapaneseUPS.status	(revision 2381)
++++ examples/status/JapaneseUPS.status	(working copy)
+@@ -1,10 +1,10 @@
+ APC      : 001,050,1103
+ DATE     : Mon Sep 11 13:51:14 JST 2000
+-HOSTNAME : master
++HOSTNAME : leader
+ RELEASE  : 3.7.2
+ CABLE    : Custom Cable Smart
+ MODEL    : APC Smart-UPS 1250
+-UPSMODE  : Net Master
++UPSMODE  : Net Leader
+ SHARE    : NetworkUPS
+ UPSNAME  : UPS_IDEN
+ STATUS   : ONLINE 
+Index: examples/status/PowerStack450.status
+===================================================================
+--- examples/status/PowerStack450.status	(revision 2381)
++++ examples/status/PowerStack450.status	(working copy)
+@@ -5,7 +5,7 @@
+ UPSNAME  : UPS_IDEN
+ CABLE    : Custom Cable Smart
+ MODEL    : PowerStack 450  
+-UPSMODE  : Net Master
++UPSMODE  : Net Leader
+ STARTTIME: Sun Mar 31 01:23:34 PST 2002
+ SHARE    : NetworkUPS
+ STATUS   : ONLINE 
+Index: examples/status/SmartUPS5000.status
+===================================================================
+--- examples/status/SmartUPS5000.status	(revision 2381)
++++ examples/status/SmartUPS5000.status	(working copy)
+@@ -1,10 +1,10 @@
+ APC      : 001,050,1145
+ DATE     : Tue Aug 29 13:35:43 CEST 2000
+-HOSTNAME : net-master
++HOSTNAME : net-leader
+ RELEASE  : 3.7.2
+ CABLE    : Custom Cable Smart
+ MODEL    : SMART-UPS 5000 RM
+-UPSMODE  : Net Master
++UPSMODE  : Net Leader
+ SHARE    : NetworkUPS
+ UPSNAME  : UPS_IDEN
+ STATUS   : ONLINE 
+Index: examples/status/newbackupspro2.status
+===================================================================
+--- examples/status/newbackupspro2.status	(revision 2381)
++++ examples/status/newbackupspro2.status	(working copy)
+@@ -3,7 +3,7 @@
+ RELEASE  : 3.7.2
+ CABLE    : APC Cable 940-0095A
+ MODEL    : BACK-UPS PRO 420
+-UPSMODE  : Net Master
++UPSMODE  : Net Leader
+ SHARE    : NetworkUPS
+ UPSNAME  : UPS_IDEN
+ STATUS   : ONLINE 
+Index: examples/upsapm.c
+===================================================================
+--- examples/upsapm.c	(revision 2381)
++++ examples/upsapm.c	(working copy)
+@@ -1,6 +1,6 @@
+ /*
+  * Client test program for apcnisd to be used
+- * as a base for the new master/slave code.
++ * as a base for the new leader/follower code.
+  *
+  * Build it with: cc upsapm.c ../lib/libapc.a -o newclient
+  *
+Index: examples/usb_hid_usages
+===================================================================
+--- examples/usb_hid_usages	(revision 2381)
++++ examples/usb_hid_usages	(working copy)
+@@ -1057,7 +1057,7 @@
+ 	0xD9	CurrentOutOfRange
+ 	0xDA	CurrentNotRegulated
+ 	0xDB	VoltageNotRegulated
+-	0xDC	MasterMode
++	0xDC	LeaderMode
+ 	0xDD	ChargerBattery/HostControlled
+ 	0xF0	ChargerSpecInfo
+ 	0xF1	ChargerSpecRef
+Index: include/defines.h
+===================================================================
+--- include/defines.h	(revision 2381)
++++ include/defines.h	(working copy)
+@@ -82,8 +82,8 @@
+ /* Extended bit values added by apcupsd */
+ #define UPS_commlost      0x00000100    /* Communications with UPS lost */
+ #define UPS_shutdown      0x00000200    /* Shutdown in progress */
+-#define UPS_slave         0x00000400    /* Set if this is a slave */
+-#define UPS_slavedown     0x00000800    /* Slave not responding */
++#define UPS_follower      0x00000400    /* Set if this is a follower */
++#define UPS_followerdown  0x00000800    /* Follower not responding */
+ #define UPS_onbatt_msg    0x00020000    /* Set when UPS_ONBATT message is sent */
+ #define UPS_fastpoll      0x00040000    /* Set on power failure to poll faster */
+ #define UPS_shut_load     0x00080000    /* Set when BatLoad <= percent */
+@@ -94,7 +94,7 @@
+ #define UPS_plugged       0x01000000    /* Set if computer is plugged into UPS */
+ #define UPS_battpresent   0x04000000    /* Indicates if battery is connected */
+ 
+-#define UPS_LOCAL_BITS (UPS_commlost|UPS_shutdown|UPS_slave|UPS_slavedown| \
++#define UPS_LOCAL_BITS (UPS_commlost|UPS_shutdown|UPS_follower|UPS_followerdown| \
+             UPS_onbatt_msg|UPS_fastpoll|UPS_plugged| \
+             UPS_shut_load|UPS_shut_btime|UPS_shut_ltime|UPS_shut_emerg)
+ 
+Index: include/struct.h
+===================================================================
+--- include/struct.h	(revision 2381)
++++ include/struct.h	(working copy)
+@@ -68,8 +68,8 @@
+ typedef enum {
+    NO_CLASS = 0,
+    STANDALONE,
+-   SHARESLAVE,
+-   SHAREMASTER,
++   SHAREFOLLOWER,
++   SHARELEADER,
+ } ClassMode;
+ 
+ typedef enum {
+@@ -158,8 +158,8 @@
+    void clear_shut_load() { Status &= ~UPS_shut_load; };
+    void clear_shut_ltime() { Status &= ~UPS_shut_ltime; };
+    void clear_shut_remote() { Status &= ~UPS_shut_remote; };
+-   void clear_slavedown() { Status &= ~UPS_slavedown; };
+-   void clear_slave() { Status &= ~UPS_slave; };
++   void clear_followerdown() { Status &= ~UPS_followerdown; };
++   void clear_follower() { Status &= ~UPS_follower; };
+    void clear_trim() { Status &= ~UPS_trim; };
+    void clear_battpresent() {Status &= ~UPS_battpresent; };
+ 
+@@ -190,9 +190,9 @@
+    void set_shut_ltime() { Status |= UPS_shut_ltime; };
+    void set_shut_ltime(int val) { if (val) set_shut_ltime(); else clear_shut_ltime(); };
+    void set_shut_remote() { Status |= UPS_shut_remote; };
+-   void set_slavedown() { Status |= UPS_slavedown; };
+-   void set_slavedown(int val) { if (val) set_slavedown(); else clear_slavedown(); };
+-   void set_slave() { Status |= UPS_slave; };
++   void set_followerdown() { Status |= UPS_followerdown; };
++   void set_followerdown(int val) { if (val) set_followerdown(); else clear_followerdown(); };
++   void set_follower() { Status |= UPS_follower; };
+    void set_trim() { Status |= UPS_trim; };
+    void set_trim(int val) { if (val) set_trim(); else clear_trim(); };
+    void set_battpresent() { Status |= UPS_battpresent; };
+@@ -215,8 +215,8 @@
+    bool is_shut_load() const { return (Status & UPS_shut_load) == UPS_shut_load; };
+    bool is_shut_ltime() const { return (Status & UPS_shut_ltime) == UPS_shut_ltime; };
+    bool is_shut_remote() const { return (Status & UPS_shut_remote) == UPS_shut_remote; };
+-   bool is_slave() const { return (Status & UPS_slave) == UPS_slave; };
+-   bool is_slavedown() const { return (Status & UPS_slavedown) == UPS_slavedown; };
++   bool is_follower() const { return (Status & UPS_follower) == UPS_follower; };
++   bool is_followerdown() const { return (Status & UPS_followerdown) == UPS_followerdown; };
+    bool is_trim() const { return (Status & UPS_trim) == UPS_trim; };
+    bool is_battpresent() const { return (Status & UPS_battpresent) == UPS_battpresent; };
+ 
+@@ -252,7 +252,7 @@
+    time_t last_time_annoy;
+    time_t last_time_nologon;
+    time_t last_time_changeme;
+-   time_t last_master_connect_time;     /* last time master connected */
++   time_t last_leader_connect_time;     /* last time leader connected */
+    time_t start_shut_ltime;
+    time_t start_shut_load;
+    time_t start_shut_lbatt;
+@@ -342,7 +342,7 @@
+    int eventfilemax;               /* max size of eventfile in kilobytes */
+    int event_fd;                   /* fd for eventfile */
+ 
+-   char master_name[APC_FILENAME_MAX];
++   char leader_name[APC_FILENAME_MAX];
+    char lockpath[APC_FILENAME_MAX];
+    int lockfile;
+ 
+Index: platforms/debian/packageinfo/examples
+===================================================================
+--- platforms/debian/packageinfo/examples	(revision 2381)
++++ platforms/debian/packageinfo/examples	(working copy)
+@@ -1,3 +1,3 @@
+ examples/apcupsd.conf
+-examples/apcupsd.slave.conf
+-examples/apcupsd.master.conf
++examples/apcupsd.follower.conf
++examples/apcupsd.leader.conf
+Index: platforms/etc/apcupsd.conf.in
+===================================================================
+--- platforms/etc/apcupsd.conf.in	(revision 2381)
++++ platforms/etc/apcupsd.conf.in	(working copy)
+@@ -48,7 +48,7 @@
+ #                            setting enables autodetection, which is
+ #                            the best choice for most installations.
+ #
+-# net       hostname:port    Network link to a master apcupsd through apcupsd's 
++# net       hostname:port    Network link to a leader apcupsd through apcupsd's 
+ #                            Network Information Server. This is used if the
+ #                            UPS powering your computer is connected to a 
+ #                            different computer for monitoring.
+@@ -236,7 +236,7 @@
+ # Remaining items are for ShareUPS (APC expansion card) ONLY
+ #
+ 
+-# UPSCLASS [ standalone | shareslave | sharemaster ]
++# UPSCLASS [ standalone | sharefollower | shareleader ]
+ #   Normally standalone unless you share an UPS using an APC ShareUPS
+ #   card.
+ UPSCLASS standalone
+Index: platforms/mingw/apccontrol.bat
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+Index: platforms/mingw/apcupsd.conf.in
+===================================================================
+--- platforms/mingw/apcupsd.conf.in	(revision 2381)
++++ platforms/mingw/apcupsd.conf.in	(working copy)
+@@ -49,7 +49,7 @@
+ #                            setting enables autodetection, which is
+ #                            the best choice for most installations.
+ #
+-# net       hostname:port    Network link to a master apcupsd through apcupsd's 
++# net       hostname:port    Network link to a leader apcupsd through apcupsd's 
+ #                            Network Information Server. This is used if the
+ #                            UPS powering your computer is connected to a 
+ #                            different computer for monitoring.
+@@ -227,7 +227,7 @@
+ # Remaining items are for ShareUPS (APC expansion card) ONLY
+ #
+ 
+-# UPSCLASS [ standalone | shareslave | sharemaster ]
++# UPSCLASS [ standalone | sharefollower | shareleader ]
+ #   Normally standalone unless you share an UPS using an APC ShareUPS
+ #   card.
+ UPSCLASS standalone
+Index: platforms/openbsd/README
+===================================================================
+--- platforms/openbsd/README	(revision 2381)
++++ platforms/openbsd/README	(working copy)
+@@ -19,7 +19,7 @@
+ 
+ For most operating systems, the following sequence occurs:
+         1. mains power loss
+-        2. warning messages are sent from the master at various intervals
++        2. warning messages are sent from the leader at various intervals
+         3. minimum battery level or max run time is reached
+         4. apcupsd invokes the control script with 'doshutdown' argument,
+            then exits
+@@ -36,7 +36,7 @@
+ modified to the following:
+ 
+         1. mains power loss
+-        2. warning messages are sent from the master at various intervals
++        2. warning messages are sent from the leader at various intervals
+         3. minimum battery level or max run time is reached
+         4. apcupsd sends message to UPS to power off after a configurable
+            number of seconds
+@@ -63,7 +63,7 @@
+ If the OpenBSD server is running in apcupsd networked mode with another
+ machine such as a Linux server, it is possible for the former to complete
+ the shutdown and the latter to cancel it.  Depending on which machine
+-is the master and which is the slave, this could either result in one
++is the leader and which is the follower, this could either result in one
+ machine remaining in a halted state indefinitely, or (worse) the other
+ machine losing power while not in a halted state.
+ 
+@@ -71,7 +71,7 @@
+ mode, that shutdown cancellation be disabled on all machines.
+ 
+ To date, the OpenBSD code has only been tested in standalone mode and
+-as a net master, with a Slackware Linux machine as the net slave.
++as a net leader, with a Slackware Linux machine as the net follower.
+ 
+ Modifying the Power Off Interval
+ --------------------------------
+Index: platforms/slackware/README
+===================================================================
+--- platforms/slackware/README	(revision 2381)
++++ platforms/slackware/README	(working copy)
+@@ -43,7 +43,7 @@
+ action.  If there is reference to rc.local in the rc.M script, then you
+ are probably safe.
+ 
+-If you are using the network feature (master-slave) of apcupsd and are
++If you are using the network feature (leader-follower) of apcupsd and are
+ running a DNS server locally, make sure the name server is up and running
+ before executing rc.apcupsd.  Since named is normally started out of
+ rc.inet2, this should be a non-issue.
+Index: platforms/yellowdog/apcupsd.spec.in
+===================================================================
+--- platforms/yellowdog/apcupsd.spec.in	(revision 2381)
++++ platforms/yellowdog/apcupsd.spec.in	(working copy)
+@@ -120,7 +120,6 @@
+         --enable-cgi \
+         --enable-pthreads \
+         --enable-net \
+-        --enable-master-slave \
+         --enable-apcsmart \
+         --enable-dumb \
+         --enable-usb \
+Index: src/action.c
+===================================================================
+--- src/action.c	(revision 2381)
++++ src/action.c	(working copy)
+@@ -161,10 +161,10 @@
+    }
+ 
+    /*
+-    * For network slaves, apcupsd needs to terminate here for now.
++    * For network followers, apcupsd needs to terminate here for now.
+     * This is sloppy, but it works. If you are networked, then the
+-    * master must fall also. This is required so that the UPS
+-    * can reboot the slaves.
++    * leader must fall also. This is required so that the UPS
++    * can reboot the followers.
+     */
+    if (ok == 3)
+       sendsig_terminate();
+@@ -210,7 +210,7 @@
+    make_file(ups, ups->pwrfailpath);
+    prohibit_logins(ups);
+ 
+-   if (!ups->is_slave()) {
++   if (!ups->is_follower()) {
+       /*
+        * Note, try avoid using this option if at all possible
+        * as it will shutoff the UPS power, and you cannot
+@@ -485,7 +485,7 @@
+       /* shutdown requested but still running */
+       if (ups->is_shutdown()) {
+          if (ups->killdelay && now - ups->ShutDown >= ups->killdelay) {
+-            if (!ups->is_slave())
++            if (!ups->is_follower())
+                initiate_hibernate(ups);
+             ups->ShutDown = now;   /* wait a bit before doing again */
+             ups->set_shutdown();
+Index: src/cgi/multimon.c
+===================================================================
+--- src/cgi/multimon.c	(revision 2381)
++++ src/cgi/multimon.c	(working copy)
+@@ -85,7 +85,7 @@
+         { "CAL",        "CALIBRATION",          1       },
+         { "CL",         "COMM LOST",            2       },
+         { "SD",         "SHUTTING DOWN",        2       },
+-        { "SLAVE",      "SLAVE",                0       },
++        { "FOLLOWER",      "FOLLOWER",                0       },
+         { NULL,         NULL,                   0       }
+ };
+ 
+@@ -185,8 +185,8 @@
+        strcat(status, "CL ");
+     if (ups_status & UPS_shutdown)
+        strcat(status, "SD ");
+-    if (ups_status & UPS_slave)
+-       strcat(status, "SLAVE ");
++    if (ups_status & UPS_follower)
++       strcat(status, "FOLLOWER ");
+ 
+     stat = strtok (status, " ");
+     while (stat != NULL) {  
+Index: src/cgi/upsstats.c
+===================================================================
+--- src/cgi/upsstats.c	(revision 2381)
++++ src/cgi/upsstats.c	(working copy)
+@@ -298,8 +298,8 @@
+              fputs("COMM LOST ", stdout); 
+          if (status & UPS_shutdown)
+              fputs("SHUTDOWN ", stdout);
+-         if (status & UPS_slave)
+-             fputs("SLAVE ", stdout);
++         if (status & UPS_follower)
++             fputs("FOLLOWER ", stdout);
+          if (!(status & UPS_battpresent))
+              fputs("NOBATT ", stdout);
+          fputs ("\n", stdout); 
+Index: src/device.c
+===================================================================
+--- src/device.c	(revision 2381)
++++ src/device.c	(working copy)
+@@ -99,9 +99,9 @@
+            "ignored at %s:%d\n", ups->pwrfailpath, __FILE__, __LINE__);
+    } else {
+       /* We are on batteries, so do the kill_power */
+-      if (ups->upsclass.type == SHAREMASTER) {
++      if (ups->upsclass.type == SHARELEADER) {
+          log_event(ups, LOG_WARNING,
+-            "Waiting 30 seconds for slave(s) to shutdown.");
++            "Waiting 30 seconds for follower(s) to shutdown.");
+          sleep(30);
+       }
+ 
+@@ -111,11 +111,11 @@
+ 
+       log_event(ups, LOG_WARNING, "Attempting to kill the UPS power!");
+ 
+-      if (ups->upsclass.type == SHARESLAVE) {
++      if (ups->upsclass.type == SHAREFOLLOWER) {
+          sleep(10);
+-         log_event(ups, LOG_WARNING, "Waiting For ShareUPS Master to shutdown");
++         log_event(ups, LOG_WARNING, "Waiting For ShareUPS Leader to shutdown");
+          sleep(60);
+-         log_event(ups, LOG_WARNING, "Failed to have power killed by Master!");
++         log_event(ups, LOG_WARNING, "Failed to have power killed by Leader!");
+ 
+          /*
+           * ***FIXME*** this really should not do a reboot here,
+Index: src/drivers/apcsmart/smartsetup.c
+===================================================================
+--- src/drivers/apcsmart/smartsetup.c	(revision 2381)
++++ src/drivers/apcsmart/smartsetup.c	(working copy)
+@@ -123,7 +123,7 @@
+    char a = 'Y';
+ 
+    if (_ups->fd == -1)
+-      return 1;                    /* we must be a slave */
++      return 1;                    /* we must be a follower */
+ 
+    /* Have to clear RTS line to access the serial cable mode PnP on BKPro */
+    /* Shouldn't hurt on other cables, so just do it all the time. */
+Index: src/drivers/dumb/dumbsetup.c
+===================================================================
+--- src/drivers/dumb/dumbsetup.c	(revision 2381)
++++ src/drivers/dumb/dumbsetup.c	(working copy)
+@@ -88,7 +88,7 @@
+    tcsetattr(_ups->fd, TCSANOW, &_newtio);
+    tcflush(_ups->fd, TCIFLUSH);
+ 
+-   _ups->clear_slave();
++   _ups->clear_follower();
+ 
+    return 1;
+ }
+Index: src/drivers/modbus/ModbusComm.cpp
+===================================================================
+--- src/drivers/modbus/ModbusComm.cpp	(revision 2381)
++++ src/drivers/modbus/ModbusComm.cpp	(working copy)
+@@ -128,8 +128,8 @@
+    if (txsz > MODBUS_MAX_PDU_SZ || rxsz > MODBUS_MAX_PDU_SZ)
+       return false;
+ 
+-   // Prepend slave address and function code
+-   txfrm[0] = _slaveaddr;
++   // Prepend follower address and function code
++   txfrm[0] = _followeraddr;
+    txfrm[1] = fc;
+ 
+    // Add PDU
+@@ -173,11 +173,11 @@
+          continue;
+       }
+ 
+-      if (rxfrm[0] != _slaveaddr)
++      if (rxfrm[0] != _followeraddr)
+       {
+-         // Not from expected slave: Retry
++         // Not from expected follower: Retry
+          Dmsg(0, "%s: Bad address (exp=%u, rx=%u)\n", 
+-            __func__, _slaveaddr, rxfrm[0]);
++            __func__, _followeraddr, rxfrm[0]);
+          continue;
+       }
+ 
+Index: src/drivers/modbus/ModbusComm.h
+===================================================================
+--- src/drivers/modbus/ModbusComm.h	(revision 2381)
++++ src/drivers/modbus/ModbusComm.h	(working copy)
+@@ -30,8 +30,8 @@
+ class ModbusComm
+ {
+ public:
+-   ModbusComm(uint8_t slaveaddr = DEFAULT_SLAVE_ADDR) : 
+-      _slaveaddr(slaveaddr), _open(false) {}
++   ModbusComm(uint8_t followeraddr = DEFAULT_FOLLOWER_ADDR) : 
++      _followeraddr(followeraddr), _open(false) {}
+    virtual ~ModbusComm() {}
+ 
+    virtual bool Open(const char *dev) = 0;
+@@ -45,7 +45,7 @@
+    uint16_t ModbusCrc(const uint8_t *data, unsigned int sz);
+ 
+    // MODBUS constants
+-   static const uint8_t DEFAULT_SLAVE_ADDR = 1;
++   static const uint8_t DEFAULT_FOLLOWER_ADDR = 1;
+ 
+    // MODBUS timeouts
+    static const unsigned int MODBUS_INTERCHAR_TIMEOUT_MS = 25; // Spec is 15, increase for compatibility with USB serial dongles
+@@ -69,7 +69,7 @@
+    virtual bool ModbusTx(const ModbusFrame *frm, unsigned int sz) = 0;
+    virtual bool ModbusRx(ModbusFrame *frm, unsigned int *sz) = 0;
+ 
+-   uint8_t _slaveaddr;
++   uint8_t _followeraddr;
+    bool _open;
+ 
+ private:
+Index: src/drivers/modbus/ModbusRs232Comm.cpp
+===================================================================
+--- src/drivers/modbus/ModbusRs232Comm.cpp	(revision 2381)
++++ src/drivers/modbus/ModbusRs232Comm.cpp	(working copy)
+@@ -44,8 +44,8 @@
+ #define O_BINARY 0
+ #endif
+ 
+-ModbusRs232Comm::ModbusRs232Comm(uint8_t slaveaddr) :
+-   ModbusComm(slaveaddr),
++ModbusRs232Comm::ModbusRs232Comm(uint8_t followeraddr) :
++   ModbusComm(followeraddr),
+    _fd(-1)
+ {
+ }
+Index: src/drivers/modbus/ModbusRs232Comm.h
+===================================================================
+--- src/drivers/modbus/ModbusRs232Comm.h	(revision 2381)
++++ src/drivers/modbus/ModbusRs232Comm.h	(working copy)
+@@ -30,7 +30,7 @@
+ class ModbusRs232Comm: public ModbusComm
+ {
+ public:
+-   ModbusRs232Comm(uint8_t slaveaddr = DEFAULT_SLAVE_ADDR);
++   ModbusRs232Comm(uint8_t followeraddr = DEFAULT_FOLLOWER_ADDR);
+    virtual ~ModbusRs232Comm() {}
+ 
+    virtual bool Open(const char *dev);
+Index: src/drivers/modbus/ModbusUsbComm.cpp
+===================================================================
+--- src/drivers/modbus/ModbusUsbComm.cpp	(revision 2381)
++++ src/drivers/modbus/ModbusUsbComm.cpp	(working copy)
+@@ -42,8 +42,8 @@
+ #define ModbusRTURx 0xFF8600FC
+ #define ModbusRTUTx 0xFF8600FD
+ 
+-ModbusUsbComm::ModbusUsbComm(uint8_t slaveaddr) :
+-   ModbusComm(slaveaddr)
++ModbusUsbComm::ModbusUsbComm(uint8_t followeraddr) :
++   ModbusComm(followeraddr)
+ {
+ }
+ 
+@@ -178,13 +178,13 @@
+       {
+          // READ_HOLDING_REGS response includes a size byte.
+          // Add 3 bytes to PDU size to account for size byte itself 
+-         // plus frame header (slaveaddr and op code).
++         // plus frame header (followeraddr and op code).
+          frmsz = rpt[3] + 3;
+       }
+       else if (rpt[2] == MODBUS_FC_WRITE_MULTIPLE_REGS)
+       {
+          // WRITE_MULTIPLE_REGS response is always a fixed length
+-         // 2 byte frame header (slaveaddr and op code)
++         // 2 byte frame header (followeraddr and op code)
+          // 2 byte register starting address
+          // 2 byte register count
+          frmsz = 6;
+Index: src/drivers/modbus/ModbusUsbComm.h
+===================================================================
+--- src/drivers/modbus/ModbusUsbComm.h	(revision 2381)
++++ src/drivers/modbus/ModbusUsbComm.h	(working copy)
+@@ -31,7 +31,7 @@
+ class ModbusUsbComm: public ModbusComm
+ {
+ public:
+-   ModbusUsbComm(uint8_t slaveaddr = DEFAULT_SLAVE_ADDR);
++   ModbusUsbComm(uint8_t followeraddr = DEFAULT_FOLLOWER_ADDR);
+    virtual ~ModbusUsbComm() {}
+ 
+    virtual bool Open(const char *dev);
+Index: src/drivers/net/net.c
+===================================================================
+--- src/drivers/net/net.c	(revision 2381)
++++ src/drivers/net/net.c	(working copy)
+@@ -294,7 +294,7 @@
+    char answer[200];
+    int stat = 1;
+    int32_t newStatus;              /* this really should be uint32_t! */
+-   int32_t masterStatus;           /* status from master */
++   int32_t leaderStatus;           /* status from leader */
+ 
+    if (!_got_caps) {
+       get_capabilities();
+@@ -322,20 +322,20 @@
+    if (!getupsvar("status", answer, sizeof(answer))) {
+       Dmsg(100, "HEY!!! Couldn't get status flag.\n");
+       stat = 0;
+-      masterStatus = 0;
++      leaderStatus = 0;
+    } else {
+       /*
+        * Make sure we don't override local bits, and that
+        * all non-local bits are set/cleared correctly.
+        *
+-       * local bits = UPS_commlost|UPS_shutdown|UPS_slave|UPS_slavedown|
++       * local bits = UPS_commlost|UPS_shutdown|UPS_follower|UPS_followerdown|
+        *              UPS_prev_onbatt|UPS_prev_battlow|UPS_onbatt_msg|
+        *              UPS_fastpoll|UPS_plugged|UPS_dev_setup
+        */
+ 
+       /* First transfer set or not set all non-local bits */
+-      masterStatus = strtol(answer, NULL, 0);
+-      newStatus = masterStatus & ~UPS_LOCAL_BITS;  /* clear local bits */
++      leaderStatus = strtol(answer, NULL, 0);
++      newStatus = leaderStatus & ~UPS_LOCAL_BITS;  /* clear local bits */
+       _ups->Status &= UPS_LOCAL_BITS;               /* clear non-local bits */
+       _ups->Status |= newStatus;                    /* set new non-local bits */
+ 
+@@ -343,20 +343,20 @@
+        * Now set any special bits, note this is set only, we do
+        * not clear these bits, but let our own core code clear them
+        */
+-      newStatus = masterStatus & (UPS_commlost | UPS_fastpoll);
++      newStatus = leaderStatus & (UPS_commlost | UPS_fastpoll);
+       _ups->Status |= newStatus;
+    }
+ 
+    Dmsg(100, "Got Status = %s 0x%x\n", answer, _ups->Status);
+ 
+-   if (masterStatus & UPS_shutdown && !_ups->is_shut_remote()) {
+-      _ups->set_shut_remote();    /* if master is shutting down so do we */
+-      log_event(_ups, LOG_ERR, "Shutdown because NIS master is shutting down.");
+-      Dmsg(100, "Set SHUT_REMOTE because of master status.\n");
++   if (leaderStatus & UPS_shutdown && !_ups->is_shut_remote()) {
++      _ups->set_shut_remote();    /* if leader is shutting down so do we */
++      log_event(_ups, LOG_ERR, "Shutdown because NIS leader is shutting down.");
++      Dmsg(100, "Set SHUT_REMOTE because of leader status.\n");
+    }
+ 
+    /*
+-    * If we lost connection with master and we
++    * If we lost connection with leader and we
+     * are running on batteries, shutdown on the fourth
+     * consequtive pass here. While on batteries, this code
+     * is called once per second.
+@@ -365,7 +365,7 @@
+       if (_comm_loss++ == 4 && !_ups->is_shut_remote()) {
+          _ups->set_shut_remote();
+          log_event(_ups, LOG_ERR,
+-            "Shutdown because loss of comm with NIS master while on batteries.");
++            "Shutdown because loss of comm with NIS leader while on batteries.");
+          Dmsg(100, "Set SHUT_REMOTE because of loss of comm on batteries.\n");
+       }
+    } else {
+@@ -380,8 +380,8 @@
+ bool NetUpsDriver::Open()
+ {
+    strlcpy(_device, _ups->device, sizeof(_device));
+-   strlcpy(_ups->master_name, _ups->device, sizeof(_ups->master_name));
+-   strlcpy(_ups->upsclass.long_name, "Net Slave", sizeof(_ups->upsclass.long_name));
++   strlcpy(_ups->leader_name, _ups->device, sizeof(_ups->leader_name));
++   strlcpy(_ups->upsclass.long_name, "Net Follower", sizeof(_ups->upsclass.long_name));
+ 
+    /* Now split the device. */
+    _hostname = _device;
+@@ -478,11 +478,11 @@
+       return 0;
+ 
+    write_lock(_ups);
+-   _ups->set_slave();
++   _ups->set_follower();
+ 
+    /* ***FIXME**** poll time needs to be scanned */
+    _ups->poll_time = time(NULL);
+-   _ups->last_master_connect_time = _ups->poll_time;
++   _ups->last_leader_connect_time = _ups->poll_time;
+ 
+    if (GETVAR(CI_VLINE, "utility"))
+       _ups->LineVoltage = atof(answer);
+Index: src/drivers/pcnet/pcnet.c
+===================================================================
+--- src/drivers/pcnet/pcnet.c	(revision 2381)
++++ src/drivers/pcnet/pcnet.c	(working copy)
+@@ -674,9 +674,9 @@
+ 
+    /*
+     * Note, we set _ups->fd here so the "core" of apcupsd doesn't
+-    * think we are a slave, which is what happens when it is -1.
++    * think we are a follower, which is what happens when it is -1.
+     * (ADK: Actually this only appears to be true for apctest as
+-    * apcupsd proper uses the UPS_slave flag.)
++    * apcupsd proper uses the UPS_follower flag.)
+     * Internally, we use the fd in our own private space
+     */
+    _ups->fd = 1;
+Index: src/drivers/snmplite/apc-oids.h
+===================================================================
+--- src/drivers/snmplite/apc-oids.h	(revision 2381)
++++ src/drivers/snmplite/apc-oids.h	(working copy)
+@@ -230,7 +230,7 @@
+ __UNUSED__ static int upsDiagIMType[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 2, -1};
+ __UNUSED__ static int upsDiagIMStatus[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 3, -1};
+ __UNUSED__ static int upsDiagIMFirmwareRev[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 4, -1};
+-__UNUSED__ static int upsDiagIMSlaveFirmwareRev[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 5, -1};
++__UNUSED__ static int upsDiagIMFollowerFirmwareRev[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 5, -1};
+ __UNUSED__ static int upsDiagIMHardwareRev[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 6, -1};
+ __UNUSED__ static int upsDiagIMSerialNum[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 7, -1};
+ __UNUSED__ static int upsDiagIMManufactureDate[] = {1, 3, 6, 1, 4, 1, 318, 1, 1, 1, 13, 1, 2, 1, 8, -1};
+Index: src/drivers/test/testdriver.c
+===================================================================
+--- src/drivers/test/testdriver.c	(revision 2381)
++++ src/drivers/test/testdriver.c	(working copy)
+@@ -57,7 +57,7 @@
+    if (!open_test_device())
+       Error_abort("Cannot open UPS device %s\n", _ups->device);
+ 
+-   _ups->clear_slave();
++   _ups->clear_follower();
+    write_unlock(_ups);
+    return true;
+ }
+Index: src/drivers/usb/bsd/bsd-usb.c
+===================================================================
+--- src/drivers/usb/bsd/bsd-usb.c	(revision 2381)
++++ src/drivers/usb/bsd/bsd-usb.c	(working copy)
+@@ -170,9 +170,9 @@
+ 
+    /*
+     * Note, we set _ups->fd here so the "core" of apcupsd doesn't
+-    * think we are a slave, which is what happens when it is -1.
++    * think we are a follower, which is what happens when it is -1.
+     * (ADK: Actually this only appears to be true for apctest as
+-    * apcupsd proper uses the UPS_slave flag.)
++    * apcupsd proper uses the UPS_follower flag.)
+     * Internally, we use the fd in our own private space   
+     */
+    _ups->fd = 1;
+@@ -693,7 +693,7 @@
+ 
+    bool rc = open_usb_device();
+ 
+-   _ups->clear_slave();
++   _ups->clear_follower();
+    write_unlock(_ups);
+    return rc;
+ }
+Index: src/drivers/usb/generic/generic-usb.c
+===================================================================
+--- src/drivers/usb/generic/generic-usb.c	(revision 2381)
++++ src/drivers/usb/generic/generic-usb.c	(working copy)
+@@ -460,14 +460,14 @@
+ 
+    /*
+     * Note, we set _ups->fd here so the "core" of apcupsd doesn't
+-    * think we are a slave, which is what happens when it is -1.
++    * think we are a follower, which is what happens when it is -1.
+     * (ADK: Actually this only appears to be true for apctest as
+-    * apcupsd proper uses the UPS_slave flag.)
++    * apcupsd proper uses the UPS_follower flag.)
+     * Internally, we use the fd in our own private space   
+     */
+    _ups->fd = 1;
+ 
+-   _ups->clear_slave();
++   _ups->clear_follower();
+    write_unlock(_ups);
+    return rc;
+ }
+Index: src/drivers/usb/linux/linux-usb.c
+===================================================================
+--- src/drivers/usb/linux/linux-usb.c	(revision 2381)
++++ src/drivers/usb/linux/linux-usb.c	(working copy)
+@@ -213,9 +213,9 @@
+ 
+    /*
+     * Note, we set _ups->fd here so the "core" of apcupsd doesn't
+-    * think we are a slave, which is what happens when it is -1.
++    * think we are a follower, which is what happens when it is -1.
+     * (ADK: Actually this only appears to be true for apctest as
+-    * apcupsd proper uses the UPS_slave flag.)
++    * apcupsd proper uses the UPS_follower flag.)
+     * Internally, we use the fd in our own private space   
+     */
+    _ups->fd = 1;
+@@ -642,7 +642,7 @@
+ 
+    bool rc = open_usb_device();
+ 
+-   _ups->clear_slave();
++   _ups->clear_follower();
+    write_unlock(_ups);
+    return rc;
+ }
+Index: src/gapcmon/gapcmon.c
+===================================================================
+--- src/gapcmon/gapcmon.c	(revision 2381)
++++ src/gapcmon/gapcmon.c	(working copy)
+@@ -4741,7 +4741,7 @@
+ 
+ /*
+  * GConf2 routine
+- * Handles changes to prefs_model, or the master list of monitors in the preferences page.
++ * Handles changes to prefs_model, or the leader list of monitors in the preferences page.
+  * Triggers for this routine should not be installed until after the 
+  * control panel has been created. 
+ */
+Index: src/lib/apcconfig.c
+===================================================================
+--- src/lib/apcconfig.c	(revision 2381)
++++ src/lib/apcconfig.c	(working copy)
+@@ -80,8 +80,8 @@
+ 
+ static const GENINFO upsclasses[] = {
+    { "standalone",     "Stand Alone",           STANDALONE },
+-   { "shareslave",     "ShareUPS Slave",        SHARESLAVE },
+-   { "sharemaster",    "ShareUPS Master",       SHAREMASTER },
++   { "sharefollower",     "ShareUPS Follower",  SHAREFOLLOWER },
++   { "shareleader",    "ShareUPS Leader",       SHARELEADER },
+    { NULL,             "*invalid-ups-class*",   NO_CLASS },
+ };
+ 
+@@ -190,7 +190,7 @@
+     */
+    {"CONTROL",    obsolete, TRUE,  (GENINFO *)"CONTROL config directive is obsolete"   },
+    {"NETACCESS",  obsolete, TRUE,  (GENINFO *)"NETACCESS config directive is obsolete" },
+-   {"MASTER",     obsolete, TRUE,  (GENINFO *)"MASTER config directive is obsolete"    },
++   {"LEADER",     obsolete, TRUE,  (GENINFO *)"LEADER config directive is obsolete"    },
+    {"USERMAGIC",  obsolete, FALSE, (GENINFO *)"USERMAGIC config directive is obsolete" },
+    {"SLAVE",      obsolete, FALSE, (GENINFO *)"SLAVE config directive is obsolete"     },
+    {"NETPORT",    obsolete, FALSE, (GENINFO *)"NETPORT config directive is obsolete"   },
+@@ -681,7 +681,7 @@
+    if (ups->annoy >= ups->annoydelay)
+       ups->annoydelay = 0;
+ 
+-   if (ups->sharenet.type == SHAREMASTER) {
++   if (ups->sharenet.type == SHARELEADER) {
+       ups->maxtime = 0;
+       ups->percent = 10;
+       ups->runtime = 5;
+Index: src/lib/apcexec.c
+===================================================================
+--- src/lib/apcexec.c	(revision 2381)
++++ src/lib/apcexec.c	(working copy)
+@@ -107,13 +107,13 @@
+       asnprintf(cmdline, sizeof(cmdline), 
+          "\"%s\" /E:4096 /c \"%s%s\" %s \"%s\" %d %d \"%s\"",
+          comspec, ups->scriptdir, APCCONTROL_FILE, cmd.command,
+-         ups->upsname, !ups->is_slave(), ups->is_plugged(), sbindir);
++         ups->upsname, !ups->is_follower(), ups->is_plugged(), sbindir);
+    } else {
+       /* WinNT/2K/Vista need quotes around the entire sub-command */
+       asnprintf(cmdline, sizeof(cmdline), 
+          "\"%s\" /c \"\"%s%s\" %s \"%s\" %d %d \"%s\"\"",
+          comspec, ups->scriptdir, APCCONTROL_FILE, cmd.command,
+-         ups->upsname, !ups->is_slave(), ups->is_plugged(), sbindir);
++         ups->upsname, !ups->is_follower(), ups->is_plugged(), sbindir);
+    }
+ 
+    /* Initialize the STARTUPINFOA struct to hide the console window */
+@@ -165,7 +165,7 @@
+       return SUCCESS;
+    }
+ 
+-   asnprintf(connected, sizeof(connected), "%d", !ups->is_slave());
++   asnprintf(connected, sizeof(connected), "%d", !ups->is_follower());
+    asnprintf(powered, sizeof(powered), "%d", (int)ups->is_plugged());
+    asnprintf(apccontrol, sizeof(apccontrol), "%s%s", ups->scriptdir, APCCONTROL_FILE);
+ 
+Index: src/lib/apcstatus.c
+===================================================================
+--- src/lib/apcstatus.c	(revision 2381)
++++ src/lib/apcstatus.c	(working copy)
+@@ -49,7 +49,7 @@
+     */
+    read_lock(ups);
+ 
+-   if (ups->poll_time == 0)        /* this is always zero on slave */
++   if (ups->poll_time == 0)        /* this is always zero on follower */
+       ups->poll_time = now;
+ 
+    /* put the last UPS poll time on the DATE record */
+@@ -73,16 +73,16 @@
+    if (ups->sharenet.type != DISABLE)
+       s_write(ups, "SHARE    : %s\n", ups->sharenet.long_name);
+ 
+-   /* If slave, send last update time/date from master */
+-   if (ups->is_slave()) {    /* we must be a slave */
+-      if (ups->last_master_connect_time == 0) {
+-         s_write(ups, "MASTERUPD: No connection to Master\n");
++   /* If follower, send last update time/date from leader */
++   if (ups->is_follower()) {    /* we must be a follower */
++      if (ups->last_leader_connect_time == 0) {
++         s_write(ups, "LEADERUPD: No connection to Leader\n");
+       } else {
+-         format_date(ups->last_master_connect_time, datetime, sizeof(datetime));
+-         s_write(ups, "MASTERUPD: %s\n", datetime);
++         format_date(ups->last_leader_connect_time, datetime, sizeof(datetime));
++         s_write(ups, "LEADERUPD: %s\n", datetime);
+       }
+ 
+-      s_write(ups, "MASTER   : %s\n", ups->master_name);
++      s_write(ups, "LEADER   : %s\n", ups->leader_name);
+    }
+ 
+    if (ups->UPS_Cap[CI_UPSMODEL])
+@@ -118,11 +118,11 @@
+    if (!ups->is_battpresent())
+       strlcat(status, "NOBATT ", sizeof(status));
+ 
+-   if (ups->is_slave())
+-      strlcat(status, "SLAVE ", sizeof(status));
++   if (ups->is_follower())
++      strlcat(status, "FOLLOWER ", sizeof(status));
+ 
+-   if (ups->is_slavedown())
+-      strlcat(status, "SLAVEDOWN", sizeof(status));
++   if (ups->is_followerdown())
++      strlcat(status, "FOLLOWERDOWN", sizeof(status));
+ 
+    /* These override the above */
+    if (ups->is_commlost())
diff --git a/gnu/packages/power.scm b/gnu/packages/power.scm
index 843a907aa5..cfa3edcab8 100644
--- a/gnu/packages/power.scm
+++ b/gnu/packages/power.scm
@@ -32,7 +32,9 @@  (define-public apcupsd
                 "/" name "-" version ".tar.gz"))
               (sha256
                (base32
-                "0rwqiyzlg9p0szf3x6q1ppvrw6f6dbpn2rc5z623fk3bkdalhxyv"))))
+                "0rwqiyzlg9p0szf3x6q1ppvrw6f6dbpn2rc5z623fk3bkdalhxyv"))
+              (patch-flags '("-p0"))
+              (patches (search-patches "apcupsd-leader-follower.patch"))))
     (outputs '("out" "doc"))
     (build-system gnu-build-system)
     (arguments
diff --git a/gnu/services/power.scm b/gnu/services/power.scm
index 72b2a40fef..3eeb5318f6 100644
--- a/gnu/services/power.scm
+++ b/gnu/services/power.scm
@@ -253,7 +253,7 @@  (define-enum cable '( simple smart ether usb
                       940-0095A 940-0095B 940-0095C 940-0625A MAM-04-02-2000))
 (define-enum type '(apcsmart usb net snmp netsnmp dumb pcnet modbus test))
 (define-enum no-logon '(disable timeout percent minutes always))
-(define-enum class '(standalone shareslave sharemaster))
+(define-enum class '(standalone sharefollower shareleader))
 (define-enum mode '(disable share))
 
 (define-configuration apcupsd-configuration
@@ -315,7 +315,7 @@  (define-configuration apcupsd-configuration
 Most new UPSes are an USB.
 
 @item net
-Network link to a master apcupsd through apcupsd's Network Information Server.
+Network link to a leader apcupsd through apcupsd's Network Information Server.
 This is used if the UPS powering your computer is connected to a different
 computer for monitoring.
 

base-commit: 8c483c12e94bcf43e4c44170f1d5fea5fbba4970
prerequisite-patch-id: 42f60b7b8949c7d41d47f400576627b868cfdacb
prerequisite-patch-id: 9c6033a9adb2f18f01259f4e0152d8b442e64edd
-- 
2.48.1