Provide hook for initializing code before the fork.
[kopensolaris-gnu/glibc.git] / login / utmp_daemon.c
index 705c8b3..6b4686d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
 
@@ -17,8 +17,8 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <assert.h>
 #include <errno.h>
-#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
 
 
 /* Descriptor for the socket.  */
-static int daemon_sock = INT_MIN;
+static int daemon_sock = -1;
 
 
 /* Functions defined here.  */
-static int setutent_daemon (int reset);
+static int setutent_daemon (void);
 static int getutent_r_daemon (struct utmp *buffer, struct utmp **result);
 static int getutid_r_daemon (const struct utmp *line, struct utmp *buffer,
                             struct utmp **result);
@@ -59,12 +59,13 @@ struct utfuncs __libc_utmp_daemon_functions =
 
 static int do_setutent (int sock);
 static int do_getutent (int sock, struct utmp *buffer);
-static int do_endutent (int sock);
-static int do_getutline (int sock, const struct utmp *line,
-                        struct utmp *buffer);
 static int do_getutid (int sock, const struct utmp *id,
                            struct utmp *buffer);
 static int do_pututline (int sock, const struct utmp *utmp);
+static int do_getutline (int sock, const struct utmp *line,
+                        struct utmp *buffer);
+static int do_pututline (int sock, const struct utmp *utmp);
+static int do_endutent (int sock);
 static int do_updwtmp (int sock, const char *file,
                       const struct utmp *utmp);
 
@@ -74,9 +75,13 @@ static int send_request (int sock, const request_header *request,
 
 
 static int
-setutent_daemon (int reset)
+setutent_daemon (void)
 {
-  if (daemon_sock == INT_MIN)
+  if (access (_PATH_UTMPD_RW, F_OK) == -1
+      && access (_PATH_UTMPD_RO, F_OK) == -1)
+    return 0;
+
+  if (daemon_sock < 0)
     {
       daemon_sock = open_socket (_PATH_UTMPD_RW);
       if (daemon_sock < 0)
@@ -86,49 +91,20 @@ setutent_daemon (int reset)
          if (daemon_sock < 0)
            return 0;
        }
-
-      /* Send request to the daemon.  */
-      if (do_setutent (daemon_sock) < 0)
-       return 0;
-    }
-  else if (reset)
-    {
-      /* Send request to the daemon.  */
-      if (do_setutent (daemon_sock) < 0)
-       return 0;
     }
 
-  return 1;
-}
-
-
-static void
-endutent_daemon (void)
-{
-  if (daemon_sock >= 0)
-    {
-      /* Send request to the daemon.  */
-      do_endutent (daemon_sock);
-      close (daemon_sock);
-    }
+  /* Send request to the daemon.  */
+  if (do_setutent (daemon_sock) < 0)
+    return 0;
 
-  daemon_sock = INT_MIN;
+  return 1;
 }
 
 
 static int
 getutent_r_daemon (struct utmp *buffer, struct utmp **result)
 {
-  /* Open connection if not already done.  */
-  if (daemon_sock == INT_MIN)
-    setutent_daemon (1);
-
-  if (daemon_sock < 0)
-    {
-      /* Not available.  */
-      *result = NULL;
-      return -1;
-    }
+  assert (daemon_sock >= 0);
 
   /* Send request to the daemon.  */
   if (do_getutent (daemon_sock, buffer) < 0)
@@ -143,20 +119,16 @@ getutent_r_daemon (struct utmp *buffer, struct utmp **result)
 
 
 static int
-getutline_r_daemon (const struct utmp *line, struct utmp *buffer,
-                   struct utmp **result)
+getutid_r_daemon (const struct utmp *id, struct utmp *buffer,
+                 struct utmp **result)
 {
-  if (daemon_sock < 0)
-    {
-      *result = NULL;
-      return -1;
-    }
+  assert (daemon_sock >= 0);
 
   /* Send request to the daemon.  */
-  if (do_getutline (daemon_sock, line, buffer) < 0)
+  if (do_getutid (daemon_sock, id, buffer) < 0)
     {
       *result = NULL;
-      return -1;;
+      return -1;
     }
 
   *result = buffer;
@@ -165,17 +137,13 @@ getutline_r_daemon (const struct utmp *line, struct utmp *buffer,
 
 
 static int
-getutid_r_daemon (const struct utmp *id, struct utmp *buffer,
-                 struct utmp **result)
+getutline_r_daemon (const struct utmp *line, struct utmp *buffer,
+                   struct utmp **result)
 {
-  if (daemon_sock < 0)
-    {
-      *result = NULL;
-      return -1;
-    }
+  assert (daemon_sock >= 0);
 
   /* Send request to the daemon.  */
-  if (do_getutid (daemon_sock, id, buffer) < 0)
+  if (do_getutline (daemon_sock, line, buffer) < 0)
     {
       *result = NULL;
       return -1;
@@ -189,13 +157,7 @@ getutid_r_daemon (const struct utmp *id, struct utmp *buffer,
 static struct utmp *
 pututline_daemon (const struct utmp *utmp)
 {
-  if (daemon_sock == INT_MIN)
-    /* The connection is closed.  Open it again.  */
-    setutent_daemon (0);
-
-  if (daemon_sock < 0)
-    /* Something went wrong.  */
-    return NULL;
+  assert (daemon_sock >= 0);
 
   /* Send request to the daemon.  */
   if (do_pututline (daemon_sock, utmp) < 0)
@@ -205,6 +167,19 @@ pututline_daemon (const struct utmp *utmp)
 }
 
 
+static void
+endutent_daemon (void)
+{
+  assert (daemon_sock >= 0);
+
+  /* Send request to the daemon.  */
+  do_endutent (daemon_sock);
+
+  close (daemon_sock);
+  daemon_sock = -1;
+}
+
+
 static int
 updwtmp_daemon (const char *file, const struct utmp *utmp)
 {
@@ -217,7 +192,10 @@ updwtmp_daemon (const char *file, const struct utmp *utmp)
 
   /* Send request to the daemon.  */
   if (do_updwtmp (sock, file, utmp) < 0)
-    return -1;
+    {
+      close (sock);
+      return -1;
+    }
 
   close (sock);
   return 0;
@@ -227,24 +205,37 @@ updwtmp_daemon (const char *file, const struct utmp *utmp)
 static int
 do_setutent (int sock)
 {
-  setutent_request request;
+  setutent_request *request;
   setutent_reply reply;
+  size_t size;
+  size_t name_len;
 
-  request.header.version = UTMPD_VERSION;
-  request.header.size = sizeof (setutent_request);
-  request.header.type = UTMPD_REQ_SETUTENT;
-  strncpy (request.file, __libc_utmp_file_name, sizeof request.file);
+  name_len = strlen (__libc_utmp_file_name) + 1;
+  size = sizeof (setutent_request) + name_len;
+
+  request = malloc (size);
+  if (request == NULL)
+    return -1;
+
+  request->header.version = UTMPD_VERSION;
+  request->header.size = size;
+  request->header.type = UTMPD_REQ_SETUTENT;
+  memcpy (request->file, __libc_utmp_file_name, name_len);
 
   reply.header.version = UTMPD_VERSION;
   reply.header.size = sizeof (setutent_reply);
   reply.header.type = UTMPD_REQ_SETUTENT;
 
-  if (send_request (sock, &request.header, &reply.header) < 0)
-    return -1;
+  if (send_request (sock, &request->header, &reply.header) < 0)
+    {
+      free (request);
+      return -1;
+    }
 
   if (reply.result < 0)
     __set_errno (reply.errnum);
 
+  free (request);
   return reply.result;
 }
 
@@ -274,24 +265,27 @@ do_getutent (int sock, struct utmp *buffer)
 }
 
 static int
-do_endutent (int sock)
+do_getutid (int sock, const struct utmp *id, struct utmp *buffer)
 {
-  endutent_request request;
-  endutent_reply reply;
+  getutid_request request;
+  getutid_reply reply;
 
   request.header.version = UTMPD_VERSION;
-  request.header.size = sizeof (endutent_request);
-  request.header.type = UTMPD_REQ_ENDUTENT;
+  request.header.size = sizeof (getutid_request);
+  request.header.type = UTMPD_REQ_GETUTID;
+  memcpy (&request.id, id, sizeof (struct utmp));
 
   reply.header.version = UTMPD_VERSION;
-  reply.header.size = sizeof (endutent_reply);
-  reply.header.type = UTMPD_REQ_ENDUTENT;
+  reply.header.size = sizeof (getutid_reply);
+  reply.header.type = UTMPD_REQ_GETUTID;
 
   if (send_request (sock, &request.header, &reply.header) < 0)
     return -1;
 
   if (reply.result < 0)
     __set_errno (reply.errnum);
+  else
+    memcpy (buffer, &reply.entry, sizeof (struct utmp));
 
   return reply.result;
 }
@@ -323,45 +317,42 @@ do_getutline (int sock, const struct utmp *line, struct utmp *buffer)
 }
 
 static int
-do_getutid (int sock, const struct utmp *id, struct utmp *buffer)
+do_pututline (int sock, const struct utmp *utmp)
 {
-  getutid_request request;
-  getutid_reply reply;
+  pututline_request request;
+  pututline_reply reply;
 
   request.header.version = UTMPD_VERSION;
-  request.header.size = sizeof (getutid_request);
-  request.header.type = UTMPD_REQ_GETUTID;
-  memcpy (&request.id, id, sizeof (struct utmp));
+  request.header.size = sizeof (pututline_request);
+  request.header.type = UTMPD_REQ_PUTUTLINE;
+  memcpy (&request.utmp, utmp, sizeof (struct utmp));
 
   reply.header.version = UTMPD_VERSION;
-  reply.header.size = sizeof (getutid_reply);
-  reply.header.type = UTMPD_REQ_GETUTID;
+  reply.header.size = sizeof (pututline_reply);
+  reply.header.type = UTMPD_REQ_PUTUTLINE;
 
   if (send_request (sock, &request.header, &reply.header) < 0)
     return -1;
 
   if (reply.result < 0)
     __set_errno (reply.errnum);
-  else
-    memcpy (buffer, &reply.entry, sizeof (struct utmp));
 
   return reply.result;
 }
 
 static int
-do_pututline (int sock, const struct utmp *utmp)
+do_endutent (int sock)
 {
-  pututline_request request;
-  pututline_reply reply;
+  endutent_request request;
+  endutent_reply reply;
 
   request.header.version = UTMPD_VERSION;
-  request.header.size = sizeof (pututline_request);
-  request.header.type = UTMPD_REQ_PUTUTLINE;
-  memcpy (&request.utmp, utmp, sizeof (struct utmp));
+  request.header.size = sizeof (endutent_request);
+  request.header.type = UTMPD_REQ_ENDUTENT;
 
   reply.header.version = UTMPD_VERSION;
-  reply.header.size = sizeof (pututline_reply);
-  reply.header.type = UTMPD_REQ_PUTUTLINE;
+  reply.header.size = sizeof (endutent_reply);
+  reply.header.type = UTMPD_REQ_ENDUTENT;
 
   if (send_request (sock, &request.header, &reply.header) < 0)
     return -1;
@@ -375,25 +366,38 @@ do_pututline (int sock, const struct utmp *utmp)
 static int
 do_updwtmp (int sock, const char *file, const struct utmp *utmp)
 {
-  updwtmp_request request;
+  updwtmp_request *request;
   updwtmp_reply reply;
+  size_t size;
+  size_t file_len;
 
-  request.header.version = UTMPD_VERSION;
-  request.header.size = sizeof (updwtmp_request);
-  request.header.type = UTMPD_REQ_UPDWTMP;
-  strncpy (request.file, file, sizeof request.file);
-  memcpy (&request.utmp, utmp, sizeof (struct utmp));
+  file_len = strlen (file) + 1;
+  size = sizeof (updwtmp_request) + file_len;
+
+  request = malloc (size);
+  if (request == NULL)
+    return -1;
+
+  request->header.version = UTMPD_VERSION;
+  request->header.size = size;
+  request->header.type = UTMPD_REQ_UPDWTMP;
+  memcpy (&request->utmp, utmp, sizeof (struct utmp));
+  memcpy (request->file, file, file_len);
 
   reply.header.version = UTMPD_VERSION;
   reply.header.size = sizeof (updwtmp_reply);
   reply.header.type = UTMPD_REQ_UPDWTMP;
 
-  if (send_request (sock, &request.header, &reply.header) < 0)
-    return -1;
+  if (send_request (sock, &request->header, &reply.header) < 0)
+    {
+      free (request);
+      return -1;
+    }
 
   if (reply.result < 0)
     __set_errno (reply.errnum);
 
+  free (request);
   return reply.result;
 }
 
@@ -405,13 +409,13 @@ open_socket (const char *name)
   struct sockaddr_un addr;
   int sock;
 
-  sock = socket (PF_UNIX, SOCK_STREAM, 0);
+  sock = __socket (PF_UNIX, SOCK_STREAM, 0);
   if (sock < 0)
     return -1;
 
   addr.sun_family = AF_UNIX;
   strcpy (addr.sun_path, name);
-  if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0)
+  if (__connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0)
     {
       close (sock);
       return -1;