The branch main has been updated by khng:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=42905aa17b7e90a1f6881d84903e58330488f4ea

commit 42905aa17b7e90a1f6881d84903e58330488f4ea
Author:     Ka Ho Ng <k...@freebsd.org>
AuthorDate: 2025-06-09 03:30:46 +0000
Commit:     Ka Ho Ng <k...@freebsd.org>
CommitDate: 2025-06-09 15:24:07 +0000

    nfsd, rpcbind: add -P option to support pidfile path
    
    The -P option, when specified opens a pidfile to a given path.
    Both daemons also install a default pid file to the corresponding
    locations, that is, /var/run/nfsd.pid and /var/run/rpcbind.pid.
    
    Sponsored by:   Juniper Networks, Inc.
    MFC after:      7 days
    Reviewed by:    rmacklem
    Differential Revision:  https://reviews.freebsd.org/D50624
---
 usr.sbin/nfsd/Makefile           |  2 ++
 usr.sbin/nfsd/Makefile.depend    |  1 +
 usr.sbin/nfsd/nfsd.8             |  7 ++++++-
 usr.sbin/nfsd/nfsd.c             | 29 ++++++++++++++++++++++++---
 usr.sbin/rpcbind/Makefile        |  2 ++
 usr.sbin/rpcbind/Makefile.depend |  1 +
 usr.sbin/rpcbind/rpcbind.8       |  8 ++++++--
 usr.sbin/rpcbind/rpcbind.c       | 43 +++++++++++++++++++++++++++++++++++++---
 8 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/nfsd/Makefile b/usr.sbin/nfsd/Makefile
index d7ca8c380c48..b6bd9a28e651 100644
--- a/usr.sbin/nfsd/Makefile
+++ b/usr.sbin/nfsd/Makefile
@@ -3,4 +3,6 @@ PACKAGE=        nfs
 PROG=  nfsd
 MAN=   nfsd.8 nfsv4.4 stablerestart.5 pnfs.4 pnfsserver.4
 
+LIBADD=        util
+
 .include <bsd.prog.mk>
diff --git a/usr.sbin/nfsd/Makefile.depend b/usr.sbin/nfsd/Makefile.depend
index 732a025c9552..7e5c47e39608 100644
--- a/usr.sbin/nfsd/Makefile.depend
+++ b/usr.sbin/nfsd/Makefile.depend
@@ -9,6 +9,7 @@ DIRDEPS = \
        lib/${CSU_DIR} \
        lib/libc \
        lib/libcompiler_rt \
+       lib/libutil \
 
 
 .include <dirdeps.mk>
diff --git a/usr.sbin/nfsd/nfsd.8 b/usr.sbin/nfsd/nfsd.8
index 992228fba752..2e5724dbce33 100644
--- a/usr.sbin/nfsd/nfsd.8
+++ b/usr.sbin/nfsd/nfsd.8
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd February 21, 2025
+.Dd May 30, 2025
 .Dt NFSD 8
 .Os
 .Sh NAME
@@ -39,6 +39,7 @@ NFS server
 .Op Fl h Ar bindip
 .Op Fl p Ar pnfs_setup
 .Op Fl m Ar mirror_level
+.Op Fl P Ar pidfile
 .Op Fl V Ar virtual_hostname
 .Op Fl Fl maxthreads Ar max_threads
 .Op Fl Fl minthreads Ar min_threads
@@ -84,6 +85,10 @@ options to re-register NFS if the rpcbind server is 
restarted.
 Unregister the NFS service with
 .Xr rpcbind 8
 without creating any servers.
+.It Fl P Ar pidfile
+Specify alternative location of a file where main process PID will be stored.
+The default location is
+.Pa /var/run/nfsd.pid .
 .It Fl V Ar virtual_hostname
 Specifies a hostname to be used as a principal name, instead of
 the default hostname.
diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c
index f1f04af192da..94c30ae6dee1 100644
--- a/usr.sbin/nfsd/nfsd.c
+++ b/usr.sbin/nfsd/nfsd.c
@@ -58,6 +58,7 @@
 
 #include <err.h>
 #include <errno.h>
+#include <libutil.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -70,6 +71,7 @@
 static int     debug = 0;
 static int     nofork = 0;
 
+#define        DEFAULT_PIDFILE         "/var/run/nfsd.pid"
 #define        NFSD_STABLERESTART      "/var/db/nfs-stablerestart"
 #define        NFSD_STABLEBACKUP       "/var/db/nfs-stablerestart.bak"
 #define        MAXNFSDCNT      256
@@ -79,6 +81,7 @@ static int    nofork = 0;
 #define NFS_VER4        4
 static pid_t children[MAXNFSDCNT]; /* PIDs of children */
 static pid_t masterpid;                   /* PID of master/parent */
+static struct pidfh *masterpidfh = NULL;       /* pidfh of master/parent */
 static int nfsdcnt;            /* number of children */
 static int nfsdcnt_set;
 static int minthreads;
@@ -161,7 +164,8 @@ main(int argc, char **argv)
        size_t jailed_size, nfs_minvers_size;
        const char *lopt;
        char **bindhost = NULL;
-       pid_t pid;
+       const char *pidfile_path = DEFAULT_PIDFILE;
+       pid_t pid, otherpid;
        struct nfsd_nfsd_args nfsdargs;
        const char *vhostname = NULL;
 
@@ -171,14 +175,14 @@ main(int argc, char **argv)
        nfsdcnt = DEFNFSDCNT;
        unregister = reregister = tcpflag = maxsock = 0;
        bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
-       getopt_shortopts = "ah:n:rdtuep:m:V:N";
+       getopt_shortopts = "ah:n:rdtuep:m:V:NP:";
        getopt_usage =
            "usage:\n"
            "  nfsd [-ardtueN] [-h bindip]\n"
            "       [-n numservers] [--minthreads #] [--maxthreads #]\n"
            "       [-p/--pnfs dsserver0:/dsserver0-mounted-on-dir,...,"
            "dsserverN:/dsserverN-mounted-on-dir] [-m mirrorlevel]\n"
-           "       [-V virtual_hostname]\n";
+           "       [-P pidfile ] [-V virtual_hostname]\n";
        while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts,
                    &longindex)) != -1)
                switch (ch) {
@@ -234,6 +238,9 @@ main(int argc, char **argv)
                case 'N':
                        nofork = 1;
                        break;
+               case 'P':
+                       pidfile_path = optarg;
+                       break;
                case 0:
                        lopt = longopts[longindex].name;
                        if (!strcmp(lopt, "minthreads")) {
@@ -415,6 +422,16 @@ main(int argc, char **argv)
                }
                exit (0);
        }
+
+       if (pidfile_path != NULL) {
+               masterpidfh = pidfile_open(pidfile_path, 0600, &otherpid);
+               if (masterpidfh == NULL) {
+                       if (errno == EEXIST)
+                               errx(1, "daemon already running, pid: %jd.",
+                                   (intmax_t)otherpid);
+                       warn("cannot open pid file");
+               }
+       }
        if (debug == 0 && nofork == 0) {
                daemon(0, 0);
                (void)signal(SIGHUP, SIG_IGN);
@@ -434,6 +451,9 @@ main(int argc, char **argv)
 
        openlog("nfsd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON);
 
+       if (masterpidfh != NULL && pidfile_write(masterpidfh) != 0)
+               syslog(LOG_ERR, "pidfile_write(): %m");
+
        /*
         * For V4, we open the stablerestart file and call nfssvc()
         * to get it loaded. This is done before the daemons do the
@@ -490,6 +510,7 @@ main(int argc, char **argv)
                if (pid) {
                        children[0] = pid;
                } else {
+                       pidfile_close(masterpidfh);
                        (void)signal(SIGUSR1, child_cleanup);
                        setproctitle("server");
                        start_server(0, &nfsdargs, vhostname);
@@ -1008,6 +1029,8 @@ nfsd_exit(int status)
 {
        killchildren();
        unregistration();
+       if (masterpidfh != NULL)
+               pidfile_remove(masterpidfh);
        exit(status);
 }
 
diff --git a/usr.sbin/rpcbind/Makefile b/usr.sbin/rpcbind/Makefile
index 1bb2d7584ed2..eadadc71310e 100644
--- a/usr.sbin/rpcbind/Makefile
+++ b/usr.sbin/rpcbind/Makefile
@@ -9,6 +9,8 @@ SRCS=   check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c 
pmap_svc.c \
 
 CFLAGS+= -DPORTMAP
 
+LIBADD=        util
+
 .if ${MK_INET6_SUPPORT} != "no"
 CFLAGS+= -DINET6
 .endif
diff --git a/usr.sbin/rpcbind/Makefile.depend b/usr.sbin/rpcbind/Makefile.depend
index 732a025c9552..7e5c47e39608 100644
--- a/usr.sbin/rpcbind/Makefile.depend
+++ b/usr.sbin/rpcbind/Makefile.depend
@@ -9,6 +9,7 @@ DIRDEPS = \
        lib/${CSU_DIR} \
        lib/libc \
        lib/libcompiler_rt \
+       lib/libutil \
 
 
 .include <dirdeps.mk>
diff --git a/usr.sbin/rpcbind/rpcbind.8 b/usr.sbin/rpcbind/rpcbind.8
index 36c7a8da9984..0132c8f6a5d0 100644
--- a/usr.sbin/rpcbind/rpcbind.8
+++ b/usr.sbin/rpcbind/rpcbind.8
@@ -1,6 +1,6 @@
 .\" Copyright 1989 AT&T
 .\" Copyright 1991 Sun Microsystems, Inc.
-.Dd July 11, 2024
+.Dd May 30, 2025
 .Dt RPCBIND 8
 .Os
 .Sh NAME
@@ -8,7 +8,7 @@
 .Nd universal addresses to RPC program number mapper
 .Sh SYNOPSIS
 .Nm
-.Op Fl 6adIiLlNswW
+.Op Fl 6adIiLlNPswW
 .Op Fl h Ar bindip
 .Sh DESCRIPTION
 The
@@ -135,6 +135,10 @@ Run in foreground mode.
 In this mode,
 .Nm
 will not fork when it starts.
+.It Fl P
+Specify alternative location of a file where main process PID will be stored.
+The default location is
+.Pa /var/run/rpcbind.pid .
 .It Fl s
 Cause
 .Nm
diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c
index 622e954f903b..d165bcd9fbfc 100644
--- a/usr.sbin/rpcbind/rpcbind.c
+++ b/usr.sbin/rpcbind/rpcbind.c
@@ -61,6 +61,7 @@
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <libutil.h>
 #include <netconfig.h>
 #include <netdb.h>
 #include <pwd.h>
@@ -86,6 +87,11 @@ int rpcbindlockfd;
 
 #define RPCBINDDLOCK "/var/run/rpcbind.lock"
 
+#define DEFAULT_PIDFILE "/var/run/rpcbind.pid"
+
+char *pidfile_path = DEFAULT_PIDFILE;
+struct pidfh *pidfh = NULL;
+
 static int runasdaemon = 0;
 int insecure = 0;
 int oldstyle_local = 0;
@@ -135,6 +141,7 @@ static struct t_bind netlink_taddr = {
 static int init_transport(struct netconfig *);
 static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
                             struct netbuf *);
+static void cleanup_pidfile(void);
 static void terminate(int);
 static void parseargs(int, char *[]);
 static void update_bound_sa(void);
@@ -163,6 +170,13 @@ main(int argc, char *argv[])
        if (flock(rpcbindlockfd, LOCK_EX|LOCK_NB) != 0 && errno == EWOULDBLOCK)
                errx(1, "another rpcbind is already running. Aborting");
 
+       if (pidfile_path != NULL) {
+               pidfh = pidfile_open(pidfile_path, 0600, NULL);
+               if (pidfh == NULL)
+                       warn("cannot open pid file");
+               atexit(cleanup_pidfile);
+       }
+
        getrlimit(RLIMIT_NOFILE, &rl);
        if (rl.rlim_cur < 128) {
                if (rl.rlim_max <= 128)
@@ -248,6 +262,9 @@ main(int argc, char *argv[])
                        err(1, "fork failed");
        }
 
+       if (pidfh != NULL && pidfile_write(pidfh) != 0)
+               syslog(LOG_ERR, "pidfile_write(): %m");
+
        if (runasdaemon) {
                struct passwd *p;
 
@@ -781,6 +798,16 @@ rbllist_add(rpcprog_t prog, rpcvers_t vers, struct 
netconfig *nconf,
        list_rbl = rbl;
 }
 
+/*
+ * atexit callback for pidfh cleanup
+ */
+static void
+cleanup_pidfile(void)
+{
+       if (pidfh != NULL)
+               pidfile_remove(pidfh);
+}
+
 /*
  * Catch the signal and die
  */
@@ -792,8 +819,15 @@ terminate(int signum)
 
        doterminate = signum;
        wr = write(terminate_wfd, &c, 1);
-       if (wr < 1)
+       if (wr < 1) {
+               /*
+                * The call to cleanup_pidfile should be async-signal safe.
+                * pidfile_remove calls fstat and funlinkat system calls, and
+                * we are exiting immediately.
+                */
+               cleanup_pidfile();
                _exit(2);
+       }
 }
 
 void
@@ -821,7 +855,7 @@ parseargs(int argc, char *argv[])
 #else
 #define WRAPOP ""
 #endif
-       while ((c = getopt(argc, argv, "6adh:IiLlNs" WRAPOP WSOP)) != -1) {
+       while ((c = getopt(argc, argv, "6adh:IiLlNP:s" WRAPOP WSOP)) != -1) {
                switch (c) {
                case '6':
                        ipv6_only = 1;
@@ -860,6 +894,9 @@ parseargs(int argc, char *argv[])
                case 's':
                        runasdaemon = 1;
                        break;
+               case 'P':
+                       pidfile_path = strdup(optarg);
+                       break;
 #ifdef LIBWRAP
                case 'W':
                        libwrap = 1;
@@ -872,7 +909,7 @@ parseargs(int argc, char *argv[])
 #endif
                default:        /* error */
                        fprintf(stderr,
-                           "usage: rpcbind [-6adIiLls%s%s] [-h bindip]\n",
+                           "usage: rpcbind [-6adIiLlNPs%s%s] [-h bindip]\n",
                            WRAPOP, WSOP);
                        exit (1);
                }

Reply via email to