A whole bunch of changes to allow building for Windows.
[gnupg.git] / tools / watchgnupg.c
index 63daab1..051ca50 100644 (file)
@@ -1,5 +1,5 @@
 /* watchgnupg.c - Socket server for GnuPG logs
- *     Copyright (C) 2003 Free Software Foundation, Inc.
+ *     Copyright (C) 2003, 2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <fcntl.h>
 #include <time.h>
 
 #define PGM "watchgnupg"
 
+/* Allow for a standalone build. */
+#ifdef VERSION
+#define MYVERSION_LINE PGM " (GnuPG) " VERSION
+#define BUGREPORT_LINE "\nReport bugs to <bug-gnupg@gnu.org>.\n"
+#else
+#define MYVERSION_LINE PGM 
+#define BUGREPORT_LINE ""
+#endif
+
+#ifndef PF_LOCAL
+# ifdef PF_UNIX
+#  define PF_LOCAL PF_UNIX
+# else
+#  define PF_LOCAL AF_UNIX
+# endif
+# ifndef AF_LOCAL
+#  define AF_LOCAL AF_UNIX
+# endif
+#endif
+
+
 static int verbose;
-static int debug;
 
 
 static void
@@ -168,6 +193,29 @@ print_line (client_t c, const char *line)
 }
 
 
+static void
+print_version (int with_help)
+{
+  fputs (MYVERSION_LINE "\n"
+         "Copyright (C) 2004 Free Software Foundation, Inc.\n"
+         "This program comes with ABSOLUTELY NO WARRANTY.\n"
+         "This is free software, and you are welcome to redistribute it\n"
+         "under certain conditions. See the file COPYING for details.\n",
+         stdout);
+        
+  if (with_help)
+    fputs ("\n"
+          "Usage: " PGM " [OPTIONS] SOCKETNAME\n"
+          "Open the local socket SOCKETNAME and display log messages\n"
+          "\n"
+          "  --force     delete an already existing socket file\n"
+          "  --verbose   enable extra informational output\n"
+          "  --version   print version of the program and exit\n"
+          "  --help      display this help and exit\n"
+          BUGREPORT_LINE, stdout );
+  
+  exit (0);
+}
 
 int 
 main (int argc, char **argv)
@@ -176,8 +224,9 @@ main (int argc, char **argv)
   int force = 0;
 
   struct sockaddr_un srvr_addr;
-  int addrlen;
+  socklen_t addrlen;
   int server;
+  int flags;
   client_t client_list = NULL;
  
   if (argc)
@@ -187,22 +236,18 @@ main (int argc, char **argv)
   while (argc && last_argc != argc )
     {
       last_argc = argc;
-      if (!strcmp (*argv, "--help"))
+      if (!strcmp (*argv, "--"))
         {
-          puts (
-                "usage: " PGM " [options] socketname\n"
-                "\n"
-                "       Options are --verbose, --debug and --force");
-          exit (0);
-        }
-      if (!strcmp (*argv, "--verbose"))
-        {
-          verbose = 1;
           argc--; argv++;
+          break;
         }
-      else if (!strcmp (*argv, "--debug"))
+      else if (!strcmp (*argv, "--version"))
+        print_version (0);
+      else if (!strcmp (*argv, "--help"))
+        print_version (1);
+      else if (!strcmp (*argv, "--verbose"))
         {
-          verbose = debug = 1;
+          verbose = 1;
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--force"))
@@ -214,7 +259,8 @@ main (int argc, char **argv)
  
   if (argc != 1)
     {
-      die ("usage: " PGM " socketname\n");
+      fprintf (stderr, "usage: " PGM " socketname\n");
+      exit (1);
     }
 
 
@@ -227,6 +273,16 @@ main (int argc, char **argv)
   if (server == -1)
     die ("socket() failed: %s\n", strerror (errno));
 
+  /* We better set the listening socket to non-blocking so that we
+     don't get bitten by race conditions in accept.  The should not
+     happen for Unix Domain sockets but well, shit happens. */
+  flags = fcntl (server, F_GETFL, 0);
+  if (flags == -1)
+    die ("fcntl (F_GETFL) failed: %s\n", strerror (errno));
+  if ( fcntl (server, F_SETFL, (flags | O_NONBLOCK)) == -1)
+    die ("fcntl (F_SETFL) failed: %s\n", strerror (errno));
+  
+
   memset (&srvr_addr, 0, sizeof srvr_addr);
   srvr_addr.sun_family = AF_LOCAL;
   strncpy (srvr_addr.sun_path, *argv, sizeof (srvr_addr.sun_path) - 1);
@@ -257,8 +313,8 @@ main (int argc, char **argv)
       client_t client;
 
       /* Usually we don't have that many connections, thus it is okay
-         to set them al the time from scratch and don't maintain an
-         active fd_set. */
+         to set them allways from scratch and don't maintain an active
+         fd_set. */
       FD_ZERO (&rfds);
       FD_SET (server, &rfds);
       max_fd = server;
@@ -282,12 +338,12 @@ main (int argc, char **argv)
           fd = accept (server, (struct sockaddr *) &clnt_addr, &addrlen);
           if (fd == -1)
             {
-              printf ("accepting connection failed: %s\n", strerror (errno));
+              printf ("[accepting connection failed: %s]\n", strerror (errno));
             }
           else if (fd >= FD_SETSIZE)
             {
               close (fd);
-              printf ("[connection request denied: too many connections\n");
+              printf ("[connection request denied: too many connections]\n");
             }
           else 
             {
@@ -305,13 +361,13 @@ main (int argc, char **argv)
             }
         }
       for (client = client_list; client; client = client->next)
-        if (client->fd != -1)
+        if (client->fd != -1 && FD_ISSET (client->fd, &rfds))
           {
             char line[256];
             int n;
             
             n = read (client->fd, line, sizeof line - 1);
-            if (n == 1)
+            if (n < 0)
               {
                 int save_errno = errno;
                 print_line (client, NULL); /* flush */