]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/rquotad/rquota_svc.c
Add option to specify directory to search for credentials cache files
[nfs-utils.git] / utils / rquotad / rquota_svc.c
index 81b692845e2da0e6e39524a7238b537ce53ac085..0785551472aa6e1f3f8109b814b321347c709e44 100644 (file)
  *          as published by the Free Software Foundation; either version
  *          2 of the License, or (at your option) any later version.
  */
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #ifdef HAVE_TCP_WRAPPER
 #include "tcpwrapper.h"
 #endif
 
 #include <unistd.h>
+#include <errno.h>
 #include <rpc/rpc.h>
 #include "rquota.h"
 #include <stdlib.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <syslog.h>
+#include <signal.h>
+#include <getopt.h>
+#include <rpcmisc.h>
+#include <nfslib.h>
 
 #ifdef __STDC__
 #define SIG_PF void(*)(int)
@@ -48,6 +56,14 @@ extern getquota_rslt *rquotaproc_getquota_2(ext_getquota_args *argp,
 extern getquota_rslt *rquotaproc_getactivequota_2(ext_getquota_args *argp,
                                                  struct svc_req *rqstp);
 
+static struct option longopts[] =
+{
+        { "help", 0, 0, 'h' },
+        { "version", 0, 0, 'v' },
+        { "port", 1, 0, 'p' },
+        { NULL, 0, 0, 0 }
+};
+
 /*
  * Global authentication credentials.
  */
@@ -66,7 +82,7 @@ static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
 #ifdef HAVE_TCP_WRAPPER
    /* remote host authorization check */
    if (!check_default("rquotad", svc_getcaller(transp),
-                     rqstp->rq_proc, (u_long) 0)) {
+                     rqstp->rq_proc, RQUOTAPROG)) {
          svcerr_auth (transp, AUTH_FAILED);
          return;
    }
@@ -138,6 +154,15 @@ static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
    xdrproc_t xdr_argument, xdr_result;
    char *(*local)(char *, struct svc_req *);
 
+#ifdef HAVE_TCP_WRAPPER
+   /* remote host authorization check */
+   if (!check_default("rquotad", svc_getcaller(transp),
+                     rqstp->rq_proc, RQUOTAPROG)) {
+         svcerr_auth (transp, AUTH_FAILED);
+         return;
+   }
+#endif
+
    /*
     * Don't bother authentication for NULLPROC.
     */
@@ -194,16 +219,77 @@ static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
    return;
 }
 
+static void
+usage(const char *prog, int n)
+{
+  fprintf(stderr, "Usage: %s [-p|--port port] [-h|-?|--help] [-v|--version]\n", prog);
+  exit(n);
+}
+
+static void
+killer (int sig)
+{
+   (void) pmap_unset(RQUOTAPROG, RQUOTAVERS);
+   (void) pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
+   syslog(LOG_ERR, "caught signal %d, un-registering and exiting.", sig);
+}
+
 int main(int argc, char **argv)
 {
    register SVCXPRT *transp;
+   int c;
+   int port = 0;
+   struct sigaction sa;
 
    (void) pmap_unset(RQUOTAPROG, RQUOTAVERS);
    (void) pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
 
    openlog("rquota", LOG_PID, LOG_DAEMON);
 
-   transp = svcudp_create(RPC_ANYSOCK);
+   while ((c = getopt_long(argc, argv, "hp:v", longopts, NULL)) != EOF) {
+     switch (c) {
+     case '?':
+     case 'h':
+       usage(argv[0], 0);
+       break;
+     case 'p':
+       port = atoi(optarg);
+       if (port < 1 || port > 65535) {
+        fprintf(stderr, "%s: bad port number: %s\n",
+                argv[0], optarg);
+        usage(argv[0], 1);
+       }
+       break;
+     case 'v':
+       printf("rquotad %s\n", VERSION);
+       exit(0);
+     default:
+       usage(argv[0], 1);
+     }
+   }
+
+   if (chdir(NFS_STATEDIR)) {
+     fprintf(stderr, "%s: chdir(%s) failed: %s\n",
+            argv [0], NFS_STATEDIR, strerror(errno));
+
+     exit(1);
+   }
+
+   /* WARNING: the following works on Linux and SysV, but not BSD! */
+   sa.sa_handler = SIG_IGN;
+   sa.sa_flags = 0;
+   sigemptyset(&sa.sa_mask);
+   sigaction(SIGCHLD, &sa, NULL);
+
+   sa.sa_handler = killer;
+   sigaction(SIGHUP, &sa, NULL);
+   sigaction(SIGINT, &sa, NULL);
+   sigaction(SIGTERM, &sa, NULL);
+
+   if (port)
+     transp = svcudp_create(makesock(port, IPPROTO_UDP));
+   else
+     transp = svcudp_create(svcudp_socket (RQUOTAPROG, 1));
    if (transp == NULL) {
       syslog(LOG_ERR, "cannot create udp service.");
       exit(1);