Print --version etc via estream
[gnupg.git] / common / sysutils.c
index 0f1857e..c6c9bda 100644 (file)
@@ -51,6 +51,8 @@
 #endif
 #include <fcntl.h>
 
+#include "setenv.h"   /* Gnulib replacement.  */
+
 #include "util.h"
 #include "i18n.h"
 
@@ -130,31 +132,20 @@ enable_core_dumps (void)
 
 
 
-/* Return a string which is used as a kind of process ID */
+/* Return a string which is used as a kind of process ID */
 const byte *
-get_session_marker( size_t *rlen )
+get_session_marker (size_t *rlen)
 {
-    static byte marker[SIZEOF_UNSIGNED_LONG*2];
-    static int initialized;
-
-    if ( !initialized ) {
-        volatile ulong aa, bb; /* we really want the uninitialized value */
-        ulong a, b;
-
-        initialized = 1;
-        /* Although this marker is guessable it is not easy to use
-         * for a faked control packet because an attacker does not
-         * have enough control about the time the verification does 
-         * take place.  Of course, we can add just more random but 
-         * than we need the random generator even for verification
-         * tasks - which does not make sense. */
-        a = aa ^ (ulong)getpid();
-        b = bb ^ (ulong)time(NULL);
-        memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
-        memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
+  static byte marker[SIZEOF_UNSIGNED_LONG*2];
+  static int initialized;
+  
+  if (!initialized)
+    {
+      gcry_create_nonce (marker, sizeof marker);
+      initialized = 1;
     }
-    *rlen = sizeof(marker);
-    return marker;
+  *rlen = sizeof (marker);
+  return marker;
 }
 
 
@@ -286,7 +277,10 @@ gnupg_sleep (unsigned int seconds)
 int
 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
 {
-#ifdef HAVE_W32_SYSTEM
+#if defined(HAVE_W32CE_SYSTEM)
+  (void)for_write;
+  return (int)fd;
+#elif defined(HAVE_W32_SYSTEM)
   int x;
 
   if (fd == GNUPG_INVALID_FD)
@@ -331,8 +325,15 @@ gnupg_tmpfile (void)
 {
 #ifdef HAVE_W32_SYSTEM
   int attempts, n;
+#ifdef HAVE_W32CE_SYSTEM
+  wchar_t buffer[MAX_PATH+7+12+1];
+# define mystrlen(a) wcslen (a)
+  wchar_t *name, *p;
+#else
   char buffer[MAX_PATH+7+12+1];
+# define mystrlen(a) strlen (a)
   char *name, *p;
+#endif
   HANDLE file;
   int pid = GetCurrentProcessId ();
   unsigned int value;
@@ -344,13 +345,18 @@ gnupg_tmpfile (void)
   sec_attr.bInheritHandle = TRUE;
 
   n = GetTempPath (MAX_PATH+1, buffer);
-  if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
+  if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
     {
-      errno = ENOENT;
+      gpg_err_set_errno (ENOENT);
       return NULL;
     }
-  p = buffer + strlen (buffer);
+  p = buffer + mystrlen (buffer);
+#ifdef HAVE_W32CE_SYSTEM
+  wcscpy (p, L"_gnupg");
+  p += 7;
+#else
   p = stpcpy (p, "_gnupg");
+#endif
   /* We try to create the directory but don't care about an error as
      it may already exist and the CreateFile would throw an error
      anyway.  */
@@ -366,7 +372,11 @@ gnupg_tmpfile (void)
           *p++ = tohex (((value >> 28) & 0x0f));
           value <<= 4;
         }
+#ifdef HAVE_W32CE_SYSTEM
+      wcscpy (p, L".tmp");
+#else
       strcpy (p, ".tmp");
+#endif
       file = CreateFile (buffer,
                          GENERIC_READ | GENERIC_WRITE,
                          0,
@@ -377,6 +387,10 @@ gnupg_tmpfile (void)
       if (file != INVALID_HANDLE_VALUE)
         {
           FILE *fp;
+#ifdef HAVE_W32CE_SYSTEM
+          int fd = (int)file;
+          fp = _wfdopen (fd, L"w+b");
+#else
           int fd = _open_osfhandle ((long)file, 0);
           if (fd == -1)
             {
@@ -384,19 +398,21 @@ gnupg_tmpfile (void)
               return NULL;
             }
           fp = fdopen (fd, "w+b");
+#endif
           if (!fp)
             {
               int save = errno;
               close (fd);
-              errno = save;
+              gpg_err_set_errno (save);
               return NULL;
             }
           return fp;
         }
       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
     }
-  errno = ENOENT;
+  gpg_err_set_errno (ENOENT);
   return NULL;
+#undef mystrlen
 #else /*!HAVE_W32_SYSTEM*/
   return tmpfile ();
 #endif /*!HAVE_W32_SYSTEM*/
@@ -471,7 +487,9 @@ gnupg_reopen_std (const char *pgmname)
 
   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
     exit (3);
-#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
+#else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
+  (void)pgmname;
+#endif
 }
 
 
@@ -479,12 +497,167 @@ gnupg_reopen_std (const char *pgmname)
 void 
 gnupg_allow_set_foregound_window (pid_t pid)
 {
-  if (!pid || pid == (pid_t)(-1))
+  if (!pid)
     log_info ("%s called with invalid pid %lu\n",
               "gnupg_allow_set_foregound_window", (unsigned long)pid);
-#ifdef HAVE_W32_SYSTEM  
-  else if (!AllowSetForegroundWindow (pid))
+#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
+  else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
                (unsigned long)pid, w32_strerror (-1));
 #endif
 }
+
+int
+gnupg_remove (const char *fname)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  int rc;
+  wchar_t *wfname;
+
+  wfname = utf8_to_wchar (fname);
+  if (!wfname)
+    rc = 0;
+  else
+    {
+      rc = DeleteFile (wfname);
+      xfree (wfname);
+    }
+  if (!rc)
+    gpg_err_set_errno (EIO);
+  return !rc;
+#else
+  return remove (fname);
+#endif
+}
+
+
+/* A wrapper around mkdir which takes a string for the mode argument.
+   This makes it easier to handle the mode argument which is not
+   defined on all systems.  The format of the modestring is
+
+      "-rwxrwxrwx"
+      
+   '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
+   write allowed, execution allowed with the first group for the user,
+   the second for the group and the third for all others.  If the
+   string is shorter than above the missing mode characters are meant
+   to be not set.  */
+int
+gnupg_mkdir (const char *name, const char *modestr)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  wchar_t *wname;
+  (void)modestr;
+  
+  wname = utf8_to_wchar (name);
+  if (!wname)
+    return -1;
+  if (!CreateDirectoryW (wname, NULL))
+    {
+      xfree (wname);
+      return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
+    }
+  xfree (wname);
+  return 0;
+#elif MKDIR_TAKES_ONE_ARG
+  (void)modestr;
+  /* Note: In the case of W32 we better use CreateDirectory and try to
+     set appropriate permissions.  However using mkdir is easier
+     because this sets ERRNO.  */
+  return mkdir (name);
+#else
+  mode_t mode = 0;
+
+  if (modestr && *modestr)
+    {
+      modestr++;
+      if (*modestr && *modestr++ == 'r')
+        mode |= S_IRUSR;
+      if (*modestr && *modestr++ == 'w')
+        mode |= S_IWUSR;
+      if (*modestr && *modestr++ == 'x')
+        mode |= S_IXUSR;
+      if (*modestr && *modestr++ == 'r')
+        mode |= S_IRGRP;
+      if (*modestr && *modestr++ == 'w')
+        mode |= S_IWGRP;
+      if (*modestr && *modestr++ == 'x')
+        mode |= S_IXGRP;
+      if (*modestr && *modestr++ == 'r')
+        mode |= S_IROTH;
+      if (*modestr && *modestr++ == 'w')
+        mode |= S_IWOTH;
+      if (*modestr && *modestr++ == 'x')
+        mode |= S_IXOTH;
+    }
+  return mkdir (name, mode);
+#endif
+}
+
+
+int
+gnupg_setenv (const char *name, const char *value, int overwrite)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  (void)name;
+  (void)value;
+  (void)overwrite;
+  return 0;
+#else
+  return setenv (name, value, overwrite);
+#endif
+}
+
+int 
+gnupg_unsetenv (const char *name)
+{
+#ifdef HAVE_W32CE_SYSTEM
+  (void)name;
+  return 0;
+#else
+# ifdef HAVE_UNSETENV
+  return unsetenv (name);
+# else
+  return putenv (name);
+# endif
+#endif
+}
+
+#ifdef HAVE_W32CE_SYSTEM
+/* There is a isatty function declaration in cegcc but it does not
+   make sense, thus we redefine it.  */
+int 
+_gnupg_isatty (int fd)
+{
+  (void)fd;
+  return 0;
+}
+#endif
+
+
+#ifdef HAVE_W32CE_SYSTEM
+/* Replacement for getenv which takes care of the our use of getenv.
+   The code is not thread safe but we expect it to work in all cases
+   because it is called for the first time early enough.  */
+char *
+_gnupg_getenv (const char *name)
+{
+  static int initialized;
+  static char *assuan_debug;
+  
+  if (!initialized)
+    {
+      assuan_debug = read_w32_registry_string (NULL, 
+                                               "\\Software\\GNU\\libassuan",
+                                               "debug");
+      initialized = 1;
+    }
+
+  if (!strcmp (name, "ASSUAN_DEBUG"))
+    return assuan_debug;
+  else
+    return NULL;
+}
+
+#endif /*HAVE_W32CE_SYSTEM*/
+