about summary refs log tree commit diff
path: root/nscd/nscd.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@hack.frob.com>2014-10-22 13:17:20 -0700
committerRoland McGrath <roland@hack.frob.com>2014-10-22 14:28:51 -0700
commitc6dfed243e0310bc3294c0fdf1816fceab024e9b (patch)
treebd587772105572514a6ed22a7ea1a82e8ede8e1f /nscd/nscd.c
parent8c2b1ed8bbd20d35314c2a602b903159fa567ffb (diff)
downloadglibc-c6dfed243e0310bc3294c0fdf1816fceab024e9b.tar.gz
glibc-c6dfed243e0310bc3294c0fdf1816fceab024e9b.tar.xz
glibc-c6dfed243e0310bc3294c0fdf1816fceab024e9b.zip
Rework some nscd code not to use variable-length struct types.
Diffstat (limited to 'nscd/nscd.c')
-rw-r--r--nscd/nscd.c164
1 files changed, 88 insertions, 76 deletions
diff --git a/nscd/nscd.c b/nscd/nscd.c
index b7704b37f8..1185ed6647 100644
--- a/nscd/nscd.c
+++ b/nscd/nscd.c
@@ -324,6 +324,75 @@ main (int argc, char **argv)
 }
 
 
+static void __attribute__ ((noreturn))
+invalidate_db (const char *dbname)
+{
+  int sock = nscd_open_socket ();
+
+  if (sock == -1)
+    exit (EXIT_FAILURE);
+
+  size_t dbname_len = strlen (dbname) + 1;
+  size_t reqlen = sizeof (request_header) + dbname_len;
+  struct
+  {
+    request_header req;
+    char dbname[];
+  } *reqdata = alloca (reqlen);
+
+  reqdata->req.key_len = dbname_len;
+  reqdata->req.version = NSCD_VERSION;
+  reqdata->req.type = INVALIDATE;
+  memcpy (reqdata->dbname, dbname, dbname_len);
+
+  ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, reqdata, reqlen,
+					     MSG_NOSIGNAL));
+
+  if (nbytes != reqlen)
+    {
+      int err = errno;
+      close (sock);
+      error (EXIT_FAILURE, err, _("write incomplete"));
+    }
+
+  /* Wait for ack.  Older nscd just closed the socket when
+     prune_cache finished, silently ignore that.  */
+  int32_t resp = 0;
+  nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
+  if (nbytes != 0 && nbytes != sizeof (resp))
+    {
+      int err = errno;
+      close (sock);
+      error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
+    }
+
+  close (sock);
+
+  if (resp != 0)
+    error (EXIT_FAILURE, resp, _("invalidation failed"));
+
+  exit (0);
+}
+
+static void __attribute__ ((noreturn))
+send_shutdown (void)
+{
+  int sock = nscd_open_socket ();
+
+  if (sock == -1)
+    exit (EXIT_FAILURE);
+
+  request_header req;
+  req.version = NSCD_VERSION;
+  req.type = SHUTDOWN;
+  req.key_len = 0;
+
+  ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &req, sizeof req,
+                                             MSG_NOSIGNAL));
+  close (sock);
+  exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
 /* Handle program arguments.  */
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
@@ -346,91 +415,34 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'K':
       if (getuid () != 0)
 	error (4, 0, _("Only root is allowed to use this option!"));
-      {
-	int sock = nscd_open_socket ();
-
-	if (sock == -1)
-	  exit (EXIT_FAILURE);
-
-	request_header req;
-	req.version = NSCD_VERSION;
-	req.type = SHUTDOWN;
-	req.key_len = 0;
-
-	ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &req,
-						   sizeof (request_header),
-						   MSG_NOSIGNAL));
-	close (sock);
-	exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
-      }
+      else
+        send_shutdown ();
+      break;
 
     case 'g':
       get_stats = true;
       break;
 
     case 'i':
+      {
+        /* Validate the database name.  */
+
+        dbtype cnt;
+        for (cnt = pwddb; cnt < lastdb; ++cnt)
+          if (strcmp (arg, dbnames[cnt]) == 0)
+            break;
+
+        if (cnt == lastdb)
+          {
+            argp_error (state, _("'%s' is not a known database"), arg);
+            return EINVAL;
+          }
+      }
       if (getuid () != 0)
 	error (4, 0, _("Only root is allowed to use this option!"));
       else
-	{
-	  int sock = nscd_open_socket ();
-
-	  if (sock == -1)
-	    exit (EXIT_FAILURE);
-
-	  dbtype cnt;
-	  for (cnt = pwddb; cnt < lastdb; ++cnt)
-	    if (strcmp (arg, dbnames[cnt]) == 0)
-	      break;
-
-	  if (cnt == lastdb)
-	    {
-	      argp_error (state, _("'%s' is not a known database"), arg);
-	      return EINVAL;
-	    }
-
-	  size_t arg_len = strlen (arg) + 1;
-	  struct
-	  {
-	    request_header req;
-	    char arg[arg_len];
-	  } reqdata;
-
-	  reqdata.req.key_len = strlen (arg) + 1;
-	  reqdata.req.version = NSCD_VERSION;
-	  reqdata.req.type = INVALIDATE;
-	  memcpy (reqdata.arg, arg, arg_len);
-
-	  ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &reqdata,
-						     sizeof (request_header)
-						     + arg_len,
-						     MSG_NOSIGNAL));
-
-	  if (nbytes != sizeof (request_header) + arg_len)
-	    {
-	      int err = errno;
-	      close (sock);
-	      error (EXIT_FAILURE, err, _("write incomplete"));
-	    }
-
-	  /* Wait for ack.  Older nscd just closed the socket when
-	     prune_cache finished, silently ignore that.  */
-	  int32_t resp = 0;
-	  nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
-	  if (nbytes != 0 && nbytes != sizeof (resp))
-	    {
-	      int err = errno;
-	      close (sock);
-	      error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
-	    }
-
-	  close (sock);
-
-	  if (resp != 0)
-	    error (EXIT_FAILURE, resp, _("invalidation failed"));
-
-	  exit (0);
-	}
+        invalidate_db (arg);
+      break;
 
     case 't':
       nthreads = atol (arg);