Fixed a problem in estream-printf.c.
authorWerner Koch <wk@gnupg.org>
Mon, 25 Jun 2007 11:54:43 +0000 (11:54 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 25 Jun 2007 11:54:43 +0000 (11:54 +0000)
Changes for Windows (gpgsm -k does now work).
Minor cleanups.

18 files changed:
autogen.sh
common/ChangeLog
common/estream-printf.c
common/estream.c
common/estream.h
common/homedir.c
common/iobuf.c
common/iobuf.h
common/sysutils.c
common/sysutils.h
doc/ChangeLog
doc/gpg.texi
g10/ChangeLog
g10/gpg.c
g10/gpgv.c
sm/ChangeLog
sm/certreqgen.c
sm/gpgsm.c

index 70b2eab..ad1464c 100755 (executable)
@@ -93,7 +93,7 @@ if test "$1" = "--build-w32"; then
             --with-zlib=${w32root} \
              --with-pth-prefix=${w32root} \
              --without-included-gettext \
             --with-zlib=${w32root} \
              --with-pth-prefix=${w32root} \
              --without-included-gettext \
-             --disable-regex
+             --disable-regex "$@"
     rc=$?
     exit $rc
 fi
     rc=$?
     exit $rc
 fi
index e80e703..c5fc79d 100644 (file)
@@ -1,3 +1,45 @@
+2007-06-25  Werner Koch  <wk@g10code.com>
+
+       * sysutils.c (translate_sys2libc_fd): New using the code from iobuf.c.
+       * iobuf.c: Include sysutils.h.
+       (iobuf_translate_file_handle): Remove.
+       (translate_file_handle): Use new function.
+
+       * estream-printf.c [TEST]: Header including fixes. 
+       (do_format): Do not append a trailing Nul.  This avoids spurious
+       Nuls in the es_printf output.
+       (estream_vsnprintf, estream_vasprintf): Take this in account.
+
+       * estream.h (struct es__stream): Change FLAGS to a bit structure.
+       (ES__FLAG_WRITING): Replace by a bit from FLAGS.  * estream.c
+       (struct estream_internal): Rename FLAGS to MODEFLAGS so that they
+       are not confused with the estream flags.
+       (es_initialize, es_create): Add arg MODEFLAGS so that we can setup
+       the intial writemode.  Changed all callers to pass them.
+       (es_convert_mode): Set O_BINARY.
+       (es_func_fd_create, es_func_fp_create, es_func_file_create) [W32]:
+       Call setmode if requested.
+       
+2007-06-24  Werner Koch  <wk@g10code.com>
+
+       * estream.c (do_fpopen, es_fpopen, es_fpopen_nc): New.
+       (es_func_fp_create, es_func_fp_read, es_func_fp_write) 
+       (es_func_fp_seek, es_func_fp_destroy): New.
+
+2007-06-22  Werner Koch  <wk@g10code.com>
+
+       * estream.c (es_fdopen): Factored code out to..
+       (do_fdopen): .. new.
+       (es_fdopen_nc): New.
+       (estream_cookie_fd): Add field NO_CLOSE. 
+       (es_func_fd_create): Add arg NO_CLOSE and changed all callers.
+       (es_func_fd_destroy): Handle the new flag.
+
+       * homedir.c (gnupg_libexecdir) [W32]: Factor code out to ..
+       (w32_rootdir): .. new.
+       (gnupg_sysconfdir, gnupg_libdir, gnupg_datadir) [W32]: Return
+       name based on w32_rootdir().
+
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * membuf.h (get_membuf_len): New.
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * membuf.h (get_membuf_len): New.
index fce5686..76d3469 100644 (file)
 #endif
 #ifdef TEST
 # include <locale.h>
 #endif
 #ifdef TEST
 # include <locale.h>
-#endif
-#ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
-#include _ESTREAM_PRINTF_EXTRA_INCLUDE
+#else
+# ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
+#  include _ESTREAM_PRINTF_EXTRA_INCLUDE
+# endif
 #endif
 #include "estream-printf.h"
 
 /* Allow redefinition of asprintf used malloc functions.  */
 #endif
 #include "estream-printf.h"
 
 /* Allow redefinition of asprintf used malloc functions.  */
-#ifdef _ESTREAM_PRINTF_MALLOC
+#if defined(_ESTREAM_PRINTF_MALLOC) && !defined(TEST)
 #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a))  
 #else
 #define my_printf_malloc(a) malloc((a))
 #endif
 #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a))  
 #else
 #define my_printf_malloc(a) malloc((a))
 #endif
-#ifdef _ESTREAM_PRINTF_FREE
+#if defined(_ESTREAM_PRINTF_FREE) && !defined(TEST)
 #define my_printf_free(a)   _ESTREAM_PRINTF_FREE((a))  
 #else
 #define my_printf_free(a)   free((a))
 #define my_printf_free(a)   _ESTREAM_PRINTF_FREE((a))  
 #else
 #define my_printf_free(a)   free((a))
@@ -1329,7 +1330,7 @@ pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg,
 /* Run the actual formatting.  OUTFNC and OUTFNCARG are the output
    functions.  FORMAT is format string ARGSPECS is the parsed format
    string, ARGSPECS_LEN the number of items in ARGSPECS.  VALUETABLE
 /* Run the actual formatting.  OUTFNC and OUTFNCARG are the output
    functions.  FORMAT is format string ARGSPECS is the parsed format
    string, ARGSPECS_LEN the number of items in ARGSPECS.  VALUETABLE
-   holds the values and may be directly addressed using the poistion
+   holds the values and may be directly addressed using the position
    arguments given by ARGSPECS.  MYERRNO is used for the "%m"
    conversion. NBYTES well be updated to reflect the number of bytes
    send to the output function. */ 
    arguments given by ARGSPECS.  MYERRNO is used for the "%m"
    conversion. NBYTES well be updated to reflect the number of bytes
    send to the output function. */ 
@@ -1449,8 +1450,8 @@ do_format (estream_printf_out_t outfnc, void *outfncarg,
     }
   
   /* Print out any trailing stuff. */
     }
   
   /* Print out any trailing stuff. */
-  s++;  /* Need to output a terminating nul; take it from format.  */
-  rc = outfnc (outfncarg, format, (n=s - format));
+  n = s - format;
+  rc = n? outfnc (outfncarg, format, n) : 0;
   if (!rc)
     *nbytes += n;
 
   if (!rc)
     *nbytes += n;
 
@@ -1619,10 +1620,8 @@ plain_stdio_out (void *outfncarg, const char *buf, size_t buflen)
 {
   FILE *fp = (FILE*)outfncarg;
 
 {
   FILE *fp = (FILE*)outfncarg;
 
-  fputs ("OUT->", fp);
   if ( fwrite (buf, buflen, 1, fp) != 1 )
     return -1;
   if ( fwrite (buf, buflen, 1, fp) != 1 )
     return -1;
-  fputs ("<-\n", fp);
   return 0;
 }
 
   return 0;
 }
 
@@ -1715,6 +1714,8 @@ estream_vsnprintf (char *buf, size_t bufsize,
   parm.used = 0;
   parm.buffer = bufsize?buf:NULL;
   rc = estream_format (fixed_buffer_out, &parm, format, arg_ptr);
   parm.used = 0;
   parm.buffer = bufsize?buf:NULL;
   rc = estream_format (fixed_buffer_out, &parm, format, arg_ptr);
+  if (!rc)
+    rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
   if (rc == -1)
     return -1;
   if (bufsize && buf && parm.count >= parm.size)
   if (rc == -1)
     return -1;
   if (bufsize && buf && parm.count >= parm.size)
@@ -1807,7 +1808,9 @@ estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
     }
   
   rc = estream_format (dynamic_buffer_out, &parm, format, arg_ptr);
     }
   
   rc = estream_format (dynamic_buffer_out, &parm, format, arg_ptr);
-
+  if (!rc)
+    rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
+  /* Fixme: Should we shrink the resulting buffer?  */
   if (rc != -1 && parm.error_flag)
     {
       rc = -1;
   if (rc != -1 && parm.error_flag)
     {
       rc = -1;
@@ -1820,9 +1823,9 @@ estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
       *bufp = NULL;
       return -1;
     }
       *bufp = NULL;
       return -1;
     }
-  
+  assert (parm.used);   /* We have at least the terminating Nul.  */
   *bufp = parm.buffer;
   *bufp = parm.buffer;
-  return parm.used - 1; /* Do not include the nul. */
+  return parm.used - 1; /* Do not include that Nul. */
 }
 
 /* A replacement for asprintf.  As with the BSD of asprintf version -1
 }
 
 /* A replacement for asprintf.  As with the BSD of asprintf version -1
@@ -1891,8 +1894,7 @@ one_test (const char *format, ...)
 static void
 run_tests (void)
 {
 static void
 run_tests (void)
 {
-#if 0
-  one_test ("%d %% %'d", 17, 19681977);
+  /*one_test ("%d %% %'d", 17, 19681977);*/
 
   one_test ("%d %% %d", 17, 768114563);
   one_test ("%d %% %d", 17, -768114563);
 
   one_test ("%d %% %d", 17, 768114563);
   one_test ("%d %% %d", 17, -768114563);
@@ -2011,7 +2013,8 @@ run_tests (void)
   one_test ("%50s", "the quick brown fox jumps over the lazy dogs back");
   one_test ("%51s", "the quick brown fox jumps over the lazy dogs back");
   one_test ("%-51s", "the quick brown fox jumps over the lazy dogs back");
   one_test ("%50s", "the quick brown fox jumps over the lazy dogs back");
   one_test ("%51s", "the quick brown fox jumps over the lazy dogs back");
   one_test ("%-51s", "the quick brown fox jumps over the lazy dogs back");
-#endif
+
+  one_test ("/%s=", "CN");
 
   one_test ("%f", 3.1415926535);
   one_test ("%f", -3.1415926535);
 
   one_test ("%f", 3.1415926535);
   one_test ("%f", -3.1415926535);
index 131ddc2..5b953b5 100644 (file)
@@ -67,6 +67,10 @@ void *memrchr (const void *block, int c, size_t size);
 
 \f
 
 
 \f
 
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
 /* Generally used types.  */
 
 typedef void *(*func_realloc_t) (void *mem, size_t size);
 /* Generally used types.  */
 
 typedef void *(*func_realloc_t) (void *mem, size_t size);
@@ -139,8 +143,6 @@ typedef void *estream_mutex_t;
 
 #define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR)
 
 
 #define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR)
 
-#define ES_FLAG_WRITING ES__FLAG_WRITING
-
 /* An internal stream object.  */
 
 struct estream_internal
 /* An internal stream object.  */
 
 struct estream_internal
@@ -148,9 +150,9 @@ struct estream_internal
   unsigned char buffer[BUFFER_BLOCK_SIZE];
   unsigned char unread_buffer[BUFFER_UNREAD_SIZE];
   estream_mutex_t lock;                 /* Lock. */
   unsigned char buffer[BUFFER_BLOCK_SIZE];
   unsigned char unread_buffer[BUFFER_UNREAD_SIZE];
   estream_mutex_t lock;                 /* Lock. */
-  void *cookie;                         /* Cookie.               */
-  void *opaque;                         /* Opaque data.          */
-  unsigned int flags;           /* Flags.                */
+  void *cookie;                         /* Cookie.                */
+  void *opaque;                         /* Opaque data.           */
+  unsigned int modeflags;       /* Flags for the backend. */
   off_t offset;
   es_cookie_read_function_t func_read;
   es_cookie_write_function_t func_write;
   off_t offset;
   es_cookie_read_function_t func_read;
   es_cookie_write_function_t func_write;
@@ -325,7 +327,7 @@ es_init_do (void)
 /* Cookie for memory objects.  */
 typedef struct estream_cookie_mem
 {
 /* Cookie for memory objects.  */
 typedef struct estream_cookie_mem
 {
-  unsigned int flags;          /* Open flags.  */
+  unsigned int modeflags;      /* Open flags.  */
   unsigned char *memory;       /* Data.  */
   size_t memory_size;          /* Size of MEMORY.  */
   size_t offset;               /* Current offset in MEMORY.  */
   unsigned char *memory;       /* Data.  */
   size_t memory_size;          /* Size of MEMORY.  */
   size_t offset;               /* Current offset in MEMORY.  */
@@ -349,7 +351,7 @@ es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie,
                    unsigned int append_zero, unsigned int dont_free,
                    char **ptr, size_t *size,
                    func_realloc_t func_realloc, func_free_t func_free,
                    unsigned int append_zero, unsigned int dont_free,
                    char **ptr, size_t *size,
                    func_realloc_t func_realloc, func_free_t func_free,
-                   unsigned int flags)
+                   unsigned int modeflags)
 {
   estream_cookie_mem_t mem_cookie;
   int err;
 {
   estream_cookie_mem_t mem_cookie;
   int err;
@@ -359,7 +361,7 @@ es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie,
     err = -1;
   else
     {
     err = -1;
   else
     {
-      mem_cookie->flags = flags;
+      mem_cookie->modeflags = modeflags;
       mem_cookie->memory = data;
       mem_cookie->memory_size = data_n;
       mem_cookie->offset = 0;
       mem_cookie->memory = data;
       mem_cookie->memory_size = data_n;
       mem_cookie->offset = 0;
@@ -416,7 +418,7 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size)
     {
       /* Regular write.  */
 
     {
       /* Regular write.  */
 
-      if (mem_cookie->flags & O_APPEND)
+      if (mem_cookie->modeflags & O_APPEND)
        /* Append to data.  */
        mem_cookie->offset = mem_cookie->data_len;
          
        /* Append to data.  */
        mem_cookie->offset = mem_cookie->data_len;
          
@@ -593,17 +595,20 @@ static es_cookie_io_functions_t estream_functions_mem =
     es_func_mem_destroy
   };
 
     es_func_mem_destroy
   };
 
+
+\f
 /* Implementation of fd I/O.  */
 
 /* Cookie for fd objects.  */
 typedef struct estream_cookie_fd
 {
 /* Implementation of fd I/O.  */
 
 /* Cookie for fd objects.  */
 typedef struct estream_cookie_fd
 {
-  int fd;
+  int fd;        /* The file descriptor we are using for actual output.  */
+  int no_close;  /* If set we won't close the file descriptor.  */
 } *estream_cookie_fd_t;
 
 /* Create function for fd objects.  */
 static int
 } *estream_cookie_fd_t;
 
 /* Create function for fd objects.  */
 static int
-es_func_fd_create (void **cookie, int fd, unsigned int flags)
+es_func_fd_create (void **cookie, int fd, unsigned int modeflags, int no_close)
 {
   estream_cookie_fd_t fd_cookie;
   int err;
 {
   estream_cookie_fd_t fd_cookie;
   int err;
@@ -613,7 +618,13 @@ es_func_fd_create (void **cookie, int fd, unsigned int flags)
     err = -1;
   else
     {
     err = -1;
   else
     {
+#ifdef HAVE_DOSISH_SYSTEM
+      /* Make sure it is in binary mode if requested.  */
+      if ( (modeflags & O_BINARY) )
+        setmode (fd, O_BINARY);
+#endif
       fd_cookie->fd = fd;
       fd_cookie->fd = fd;
+      fd_cookie->no_close = no_close;
       *cookie = fd_cookie;
       err = 0;
     }
       *cookie = fd_cookie;
       err = 0;
     }
@@ -680,7 +691,7 @@ es_func_fd_destroy (void *cookie)
 
   if (fd_cookie)
     {
 
   if (fd_cookie)
     {
-      err = close (fd_cookie->fd);
+      err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
       ES_MEM_FREE (fd_cookie);
     }
   else
       ES_MEM_FREE (fd_cookie);
     }
   else
@@ -689,6 +700,7 @@ es_func_fd_destroy (void *cookie)
   return err;
 }
 
   return err;
 }
 
+
 static es_cookie_io_functions_t estream_functions_fd =
   {
     es_func_fd_read,
 static es_cookie_io_functions_t estream_functions_fd =
   {
     es_func_fd_read,
@@ -697,12 +709,132 @@ static es_cookie_io_functions_t estream_functions_fd =
     es_func_fd_destroy
   };
 
     es_func_fd_destroy
   };
 
+
+
+\f
+/* Implementation of FILE* I/O.  */
+
+/* Cookie for fp objects.  */
+typedef struct estream_cookie_fp
+{
+  FILE *fp;      /* The file pointer we are using for actual output.  */
+  int no_close;  /* If set we won't close the file pointer.  */
+} *estream_cookie_fp_t;
+
+/* Create function for fd objects.  */
+static int
+es_func_fp_create (void **cookie, FILE *fp, unsigned int modeflags, int no_close)
+{
+  estream_cookie_fp_t fp_cookie;
+  int err;
+
+  fp_cookie = ES_MEM_ALLOC (sizeof *fp_cookie);
+  if (!fp_cookie)
+    err = -1;
+  else
+    {
+#ifdef HAVE_DOSISH_SYSTEM
+      /* Make sure it is in binary mode if requested.  */
+      if ( (modeflags & O_BINARY) )
+        setmode (fileno (fp), O_BINARY);
+#endif
+      fp_cookie->fp = fp;
+      fp_cookie->no_close = no_close;
+      *cookie = fp_cookie;
+      err = 0;
+    }
+  
+  return err;
+}
+
+/* Read function for FILE* objects.  */
+static ssize_t
+es_func_fp_read (void *cookie, void *buffer, size_t size)
+
+{
+  estream_cookie_fp_t file_cookie = cookie;
+  ssize_t bytes_read;
+
+  bytes_read = fread (buffer, 1, size, file_cookie->fp);
+  if (!bytes_read && ferror (file_cookie->fp))
+    return -1;
+  return bytes_read;
+}
+
+/* Write function for FILE* objects.  */
+static ssize_t
+es_func_fp_write (void *cookie, const void *buffer, size_t size)
+                          
+{
+  estream_cookie_fp_t file_cookie = cookie;
+  size_t bytes_written;
+
+  bytes_written = fwrite (buffer, 1, size, file_cookie->fp);
+  if (bytes_written != size)
+    return -1;
+  return bytes_written;
+}
+
+/* Seek function for FILE* objects.  */
+static int
+es_func_fp_seek (void *cookie, off_t *offset, int whence)
+{
+  estream_cookie_fp_t file_cookie = cookie;
+  long int offset_new;
+
+  if ( fseek (file_cookie->fp, (long int)*offset, whence) )
+    {
+      fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", errno,strerror (errno));
+    return -1;
+    }
+
+  offset_new = ftell (file_cookie->fp);
+  if (offset_new == -1)
+    {
+      fprintf (stderr, "\nftell failed: errno=%d (%s)\n", errno,strerror (errno));
+    return -1;
+    }
+  *offset = offset_new;
+  return 0;
+}
+
+/* Destroy function for fd objects.  */
+static int
+es_func_fp_destroy (void *cookie)
+{
+  estream_cookie_fp_t fp_cookie = cookie;
+  int err;
+
+  if (fp_cookie)
+    {
+      fflush (fp_cookie->fp);
+      err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp);
+      ES_MEM_FREE (fp_cookie);
+    }
+  else
+    err = 0;
+
+  return err;
+}
+
+
+static es_cookie_io_functions_t estream_functions_fp =
+  {
+    es_func_fp_read,
+    es_func_fp_write,
+    es_func_fp_seek,
+    es_func_fp_destroy
+  };
+
+
+
+\f
 /* Implementation of file I/O.  */
 
 /* Create function for file objects.  */
 static int
 es_func_file_create (void **cookie, int *filedes,
 /* Implementation of file I/O.  */
 
 /* Create function for file objects.  */
 static int
 es_func_file_create (void **cookie, int *filedes,
-                    const char *path, unsigned int flags)
+                    const char *path, unsigned int modeflags)
 {
   estream_cookie_fd_t file_cookie;
   int err;
 {
   estream_cookie_fd_t file_cookie;
   int err;
@@ -718,12 +850,17 @@ es_func_file_create (void **cookie, int *filedes,
       goto out;
     }
 
       goto out;
     }
 
-  fd = open (path, flags, ES_DEFAULT_OPEN_MODE);
+  fd = open (path, modeflags, ES_DEFAULT_OPEN_MODE);
   if (fd == -1)
     {
       err = -1;
       goto out;
     }
   if (fd == -1)
     {
       err = -1;
       goto out;
     }
+#ifdef HAVE_DOSISH_SYSTEM
+  /* Make sure it is in binary mode if requested.  */
+  if ( (modeflags & O_BINARY) )
+    setmode (fd, O_BINARY);
+#endif
 
   file_cookie->fd = fd;
   *cookie = file_cookie;
 
   file_cookie->fd = fd;
   *cookie = file_cookie;
@@ -750,16 +887,10 @@ static es_cookie_io_functions_t estream_functions_file =
 /* Stream primitives.  */
 
 static int
 /* Stream primitives.  */
 
 static int
-es_convert_mode (const char *mode, unsigned int *flags)
+es_convert_mode (const char *mode, unsigned int *modeflags)
 {
 
 {
 
-  /* FIXME: We need to allow all mode flags permutations and for
-     binary mode we need to do a
-
-     #ifdef HAVE_DOSISH_SYSTEM
-       setmode (fd, O_BINARY);
-     #endif
-  */
+  /* FIXME: We need to allow all mode flags permutations.  */
   struct
   {
     const char *mode;
   struct
   {
     const char *mode;
@@ -767,33 +898,34 @@ es_convert_mode (const char *mode, unsigned int *flags)
   } mode_flags[] = { { "r",
                       O_RDONLY },
                     { "rb",
   } mode_flags[] = { { "r",
                       O_RDONLY },
                     { "rb",
-                      O_RDONLY },
+                      O_RDONLY | O_BINARY },
                     { "w",
                       O_WRONLY | O_TRUNC | O_CREAT },
                     { "wb",
                     { "w",
                       O_WRONLY | O_TRUNC | O_CREAT },
                     { "wb",
-                      O_WRONLY | O_TRUNC | O_CREAT },
+                      O_WRONLY | O_TRUNC | O_CREAT | O_BINARY },
                     { "a",
                       O_WRONLY | O_APPEND | O_CREAT },
                     { "ab",
                     { "a",
                       O_WRONLY | O_APPEND | O_CREAT },
                     { "ab",
-                      O_WRONLY | O_APPEND | O_CREAT },
+                      O_WRONLY | O_APPEND | O_CREAT | O_BINARY },
                     { "r+",
                       O_RDWR },
                     { "rb+",
                     { "r+",
                       O_RDWR },
                     { "rb+",
-                      O_RDWR },
+                      O_RDWR | O_BINARY },
                     { "r+b",
                     { "r+b",
-                      O_RDONLY | O_WRONLY },
+                      O_RDONLY | O_WRONLY | O_BINARY },
                     { "w+",
                       O_RDWR | O_TRUNC | O_CREAT },
                     { "wb+",
                     { "w+",
                       O_RDWR | O_TRUNC | O_CREAT },
                     { "wb+",
-                      O_RDWR | O_TRUNC | O_CREAT },
+                      O_RDWR | O_TRUNC | O_CREAT | O_BINARY },
                     { "w+b",
                     { "w+b",
-                      O_RDWR | O_TRUNC | O_CREAT },
+                      O_RDWR | O_TRUNC | O_CREAT | O_BINARY },
                     { "a+",
                       O_RDWR | O_CREAT | O_APPEND },
                     { "ab+",
                     { "a+",
                       O_RDWR | O_CREAT | O_APPEND },
                     { "ab+",
-                      O_RDWR | O_CREAT | O_APPEND },
+                      O_RDWR | O_CREAT | O_APPEND | O_BINARY },
                     { "a+b",
                     { "a+b",
-                      O_RDWR | O_CREAT | O_APPEND } };
+                      O_RDWR | O_CREAT | O_APPEND | O_BINARY }
+  };
   unsigned int i;
   int err; 
 
   unsigned int i;
   int err; 
 
@@ -808,7 +940,7 @@ es_convert_mode (const char *mode, unsigned int *flags)
   else
     {
       err = 0;
   else
     {
       err = 0;
-      *flags = mode_flags[i].flags;
+      *modeflags = mode_flags[i].flags;
     }
 
   return err;
     }
 
   return err;
@@ -868,7 +1000,7 @@ es_flush (estream_t stream)
   es_cookie_write_function_t func_write = stream->intern->func_write;
   int err;
 
   es_cookie_write_function_t func_write = stream->intern->func_write;
   int err;
 
-  assert (stream->flags & ES_FLAG_WRITING);
+  assert (stream->flags.writing);
 
   if (stream->data_offset)
     {
 
   if (stream->data_offset)
     {
@@ -935,7 +1067,7 @@ es_flush (estream_t stream)
 static void
 es_empty (estream_t stream)
 {
 static void
 es_empty (estream_t stream)
 {
-  assert (! (stream->flags & ES_FLAG_WRITING));
+  assert (!stream->flags.writing);
   stream->data_len = 0;
   stream->data_offset = 0;
   stream->unread_data_len = 0;
   stream->data_len = 0;
   stream->data_offset = 0;
   stream->unread_data_len = 0;
@@ -944,7 +1076,8 @@ es_empty (estream_t stream)
 /* Initialize STREAM.  */
 static void
 es_initialize (estream_t stream,
 /* Initialize STREAM.  */
 static void
 es_initialize (estream_t stream,
-              void *cookie, int fd, es_cookie_io_functions_t functions)
+              void *cookie, int fd, es_cookie_io_functions_t functions,
+               unsigned int modeflags)
 {
   stream->intern->cookie = cookie;
   stream->intern->opaque = NULL;
 {
   stream->intern->cookie = cookie;
   stream->intern->opaque = NULL;
@@ -967,7 +1100,15 @@ es_initialize (estream_t stream,
   stream->data_offset = 0;
   stream->data_flushed = 0;
   stream->unread_data_len = 0;
   stream->data_offset = 0;
   stream->data_flushed = 0;
   stream->unread_data_len = 0;
-  stream->flags = 0;
+  /* Depending on the modeflags we set whether we start in writing or
+     reading mode.  This is required in case we are working on a
+     wronly stream which is not seeekable (like stdout).  Without this
+     pre-initialization we would do a seek at the first write call and
+     as this will fail no utput will be delivered. */
+  if ((modeflags & O_WRONLY) || (modeflags & O_RDWR) )
+    stream->flags.writing = 1;
+  else
+    stream->flags.writing = 0;
 }
 
 /* Deinitialize STREAM.  */
 }
 
 /* Deinitialize STREAM.  */
@@ -988,7 +1129,7 @@ es_deinitialize (estream_t stream)
   func_close = stream->intern->func_close;
 
   err = 0;
   func_close = stream->intern->func_close;
 
   err = 0;
-  if (stream->flags & ES_FLAG_WRITING)
+  if (stream->flags.writing)
     SET_UNLESS_NONZERO (err, tmp_err, es_flush (stream));
   if (func_close)
     SET_UNLESS_NONZERO (err, tmp_err, (*func_close) (stream->intern->cookie));
     SET_UNLESS_NONZERO (err, tmp_err, es_flush (stream));
   if (func_close)
     SET_UNLESS_NONZERO (err, tmp_err, (*func_close) (stream->intern->cookie));
@@ -1000,7 +1141,7 @@ es_deinitialize (estream_t stream)
 /* Create a new stream object, initialize it.  */
 static int
 es_create (estream_t *stream, void *cookie, int fd,
 /* Create a new stream object, initialize it.  */
 static int
 es_create (estream_t *stream, void *cookie, int fd,
-          es_cookie_io_functions_t functions)
+          es_cookie_io_functions_t functions, unsigned int modeflags)
 {
   estream_internal_t stream_internal_new;
   estream_t stream_new;
 {
   estream_internal_t stream_internal_new;
   estream_t stream_new;
@@ -1030,7 +1171,7 @@ es_create (estream_t *stream, void *cookie, int fd,
   stream_new->intern = stream_internal_new;
 
   ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock);
   stream_new->intern = stream_internal_new;
 
   ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock);
-  es_initialize (stream_new, cookie, fd, functions);
+  es_initialize (stream_new, cookie, fd, functions, modeflags);
 
   err = es_list_add (stream_new);
   if (err)
 
   err = es_list_add (stream_new);
   if (err)
@@ -1186,13 +1327,13 @@ es_readn (estream_t ES__RESTRICT stream,
   data_read = 0;
   err = 0;
 
   data_read = 0;
   err = 0;
 
-  if (stream->flags & ES_FLAG_WRITING)
+  if (stream->flags.writing)
     {
       /* Switching to reading mode -> flush output.  */
       err = es_flush (stream);
       if (err)
        goto out;
     {
       /* Switching to reading mode -> flush output.  */
       err = es_flush (stream);
       if (err)
        goto out;
-      stream->flags &= ~ES_FLAG_WRITING;
+      stream->flags.writing = 0;
     }  
 
   /* Read unread data first.  */
     }  
 
   /* Read unread data first.  */
@@ -1274,14 +1415,14 @@ es_seek (estream_t ES__RESTRICT stream, off_t offset, int whence,
       goto out;
     }
 
       goto out;
     }
 
-  if (stream->flags & ES_FLAG_WRITING)
+  if (stream->flags.writing)
     {
       /* Flush data first in order to prevent flushing it to the wrong
         offset.  */
       err = es_flush (stream);
       if (err)
        goto out;
     {
       /* Flush data first in order to prevent flushing it to the wrong
         offset.  */
       err = es_flush (stream);
       if (err)
        goto out;
-      stream->flags &= ~ES_FLAG_WRITING;
+      stream->flags.writing = 0;
     }
 
   off = offset;
     }
 
   off = offset;
@@ -1451,7 +1592,7 @@ es_writen (estream_t ES__RESTRICT stream,
   data_written = 0;
   err = 0;
   
   data_written = 0;
   err = 0;
   
-  if (! (stream->flags & ES_FLAG_WRITING))
+  if (!stream->flags.writing)
     {
       /* Switching to writing mode -> discard input data and seek to
         position at which reading has stopped.  We can do this only
     {
       /* Switching to writing mode -> discard input data and seek to
         position at which reading has stopped.  We can do this only
@@ -1489,8 +1630,8 @@ es_writen (estream_t ES__RESTRICT stream,
   if (bytes_written)
     *bytes_written = data_written;
   if (data_written)
   if (bytes_written)
     *bytes_written = data_written;
   if (data_written)
-    if (! (stream->flags & ES_FLAG_WRITING))
-      stream->flags |= ES_FLAG_WRITING;
+    if (!stream->flags.writing)
+      stream->flags.writing = 1;
 
   return err;
 }
 
   return err;
 }
@@ -1502,13 +1643,13 @@ es_peek (estream_t ES__RESTRICT stream, unsigned char **ES__RESTRICT data,
 {
   int err;
 
 {
   int err;
 
-  if (stream->flags & ES_FLAG_WRITING)
+  if (stream->flags.writing)
     {
       /* Switching to reading mode -> flush output.  */
       err = es_flush (stream);
       if (err)
        goto out;
     {
       /* Switching to reading mode -> flush output.  */
       err = es_flush (stream);
       if (err)
        goto out;
-      stream->flags &= ~ES_FLAG_WRITING;
+      stream->flags.writing = 0;
     }  
 
   if (stream->data_offset == stream->data_len)
     }  
 
   if (stream->data_offset == stream->data_len)
@@ -1572,12 +1713,13 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
   line_stream_cookie = NULL;
 
   err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, BUFFER_BLOCK_SIZE,
   line_stream_cookie = NULL;
 
   err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, BUFFER_BLOCK_SIZE,
-                           1, 0, 0, NULL, 0, ES_MEM_REALLOC, ES_MEM_FREE, O_RDWR);
+                           1, 0, 0, NULL, 0, ES_MEM_REALLOC, ES_MEM_FREE,
+                            O_RDWR);
   if (err)
     goto out;
 
   err = es_create (&line_stream, line_stream_cookie, -1,
   if (err)
     goto out;
 
   err = es_create (&line_stream, line_stream_cookie, -1,
-                  estream_functions_mem);
+                  estream_functions_mem, O_RDWR);
   if (err)
     goto out;
 
   if (err)
     goto out;
 
@@ -1738,7 +1880,7 @@ es_set_buffering (estream_t ES__RESTRICT stream,
   int err;
 
   /* Flush or empty buffer depending on mode.  */
   int err;
 
   /* Flush or empty buffer depending on mode.  */
-  if (stream->flags & ES_FLAG_WRITING)
+  if (stream->flags.writing)
     {
       err = es_flush (stream);
       if (err)
     {
       err = es_flush (stream);
       if (err)
@@ -1839,7 +1981,7 @@ es_init (void)
 estream_t
 es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
 {
 estream_t
 es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
 {
-  unsigned int flags;
+  unsigned int modeflags;
   int create_called;
   estream_t stream;
   void *cookie;
   int create_called;
   estream_t stream;
   void *cookie;
@@ -1850,16 +1992,16 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
   cookie = NULL;
   create_called = 0;
 
   cookie = NULL;
   create_called = 0;
 
-  err = es_convert_mode (mode, &flags);
+  err = es_convert_mode (mode, &modeflags);
   if (err)
     goto out;
   
   if (err)
     goto out;
   
-  err = es_func_file_create (&cookie, &fd, path, flags);
+  err = es_func_file_create (&cookie, &fd, path, modeflags);
   if (err)
     goto out;
 
   create_called = 1;
   if (err)
     goto out;
 
   create_called = 1;
-  err = es_create (&stream, cookie, fd, estream_functions_file);
+  err = es_create (&stream, cookie, fd, estream_functions_file, modeflags);
   if (err)
     goto out;
 
   if (err)
     goto out;
 
@@ -1878,7 +2020,7 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
          func_realloc_t func_realloc, func_free_t func_free,
          const char *ES__RESTRICT mode)
 {
          func_realloc_t func_realloc, func_free_t func_free,
          const char *ES__RESTRICT mode)
 {
-  unsigned int flags;
+  unsigned int modeflags;
   int create_called;
   estream_t stream;
   void *cookie;
   int create_called;
   estream_t stream;
   void *cookie;
@@ -1888,18 +2030,18 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
   stream = NULL;
   create_called = 0;
   
   stream = NULL;
   create_called = 0;
   
-  err = es_convert_mode (mode, &flags);
+  err = es_convert_mode (mode, &modeflags);
   if (err)
     goto out;
 
   err = es_func_mem_create (&cookie, data, data_n, data_len,
                            BUFFER_BLOCK_SIZE, grow, 0, 0,
   if (err)
     goto out;
 
   err = es_func_mem_create (&cookie, data, data_n, data_len,
                            BUFFER_BLOCK_SIZE, grow, 0, 0,
-                           NULL, 0, func_realloc, func_free, flags);
+                           NULL, 0, func_realloc, func_free, modeflags);
   if (err)
     goto out;
   
   create_called = 1;
   if (err)
     goto out;
   
   create_called = 1;
-  err = es_create (&stream, cookie, -1, estream_functions_mem);
+  err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags);
 
  out:
 
 
  out:
 
@@ -1913,25 +2055,25 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
 estream_t
 es_open_memstream (char **ptr, size_t *size)
 {
 estream_t
 es_open_memstream (char **ptr, size_t *size)
 {
-  unsigned int flags;
+  unsigned int modeflags;
   int create_called;
   estream_t stream;
   void *cookie;
   int err;
 
   int create_called;
   estream_t stream;
   void *cookie;
   int err;
 
-  flags = O_RDWR;
+  modeflags = O_RDWR;
   create_called = 0;
   stream = NULL;
   cookie = 0;
   
   err = es_func_mem_create (&cookie, NULL, 0, 0,
                            BUFFER_BLOCK_SIZE, 1, 1, 1,
   create_called = 0;
   stream = NULL;
   cookie = 0;
   
   err = es_func_mem_create (&cookie, NULL, 0, 0,
                            BUFFER_BLOCK_SIZE, 1, 1, 1,
-                           ptr, size, ES_MEM_REALLOC, ES_MEM_FREE, flags);
+                           ptr, size, ES_MEM_REALLOC, ES_MEM_FREE, modeflags);
   if (err)
     goto out;
   
   create_called = 1;
   if (err)
     goto out;
   
   create_called = 1;
-  err = es_create (&stream, cookie, -1, estream_functions_mem);
+  err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags);
 
  out:
 
 
  out:
 
@@ -1947,18 +2089,18 @@ es_fopencookie (void *ES__RESTRICT cookie,
                const char *ES__RESTRICT mode,
                es_cookie_io_functions_t functions)
 {
                const char *ES__RESTRICT mode,
                es_cookie_io_functions_t functions)
 {
-  unsigned int flags;
+  unsigned int modeflags;
   estream_t stream;
   int err;
 
   stream = NULL;
   estream_t stream;
   int err;
 
   stream = NULL;
-  flags = 0;
+  modeflags = 0;
   
   
-  err = es_convert_mode (mode, &flags);
+  err = es_convert_mode (mode, &modeflags);
   if (err)
     goto out;
 
   if (err)
     goto out;
 
-  err = es_create (&stream, cookie, -1, functions);
+  err = es_create (&stream, cookie, -1, functions, modeflags);
   if (err)
     goto out;
 
   if (err)
     goto out;
 
@@ -1969,9 +2111,9 @@ es_fopencookie (void *ES__RESTRICT cookie,
 
 
 estream_t
 
 
 estream_t
-es_fdopen (int filedes, const char *mode)
+do_fdopen (int filedes, const char *mode, int no_close)
 {
 {
-  unsigned int flags;
+  unsigned int modeflags;
   int create_called;
   estream_t stream;
   void *cookie;
   int create_called;
   estream_t stream;
   void *cookie;
@@ -1981,16 +2123,16 @@ es_fdopen (int filedes, const char *mode)
   cookie = NULL;
   create_called = 0;
 
   cookie = NULL;
   create_called = 0;
 
-  err = es_convert_mode (mode, &flags);
+  err = es_convert_mode (mode, &modeflags);
   if (err)
     goto out;
 
   if (err)
     goto out;
 
-  err = es_func_fd_create (&cookie, filedes, flags);
+  err = es_func_fd_create (&cookie, filedes, modeflags, no_close);
   if (err)
     goto out;
 
   create_called = 1;
   if (err)
     goto out;
 
   create_called = 1;
-  err = es_create (&stream, cookie, filedes, estream_functions_fd);
+  err = es_create (&stream, cookie, filedes, estream_functions_fd, modeflags);
 
  out:
 
 
  out:
 
@@ -1999,7 +2141,78 @@ es_fdopen (int filedes, const char *mode)
 
   return stream;
 }
 
   return stream;
 }
+
+estream_t
+es_fdopen (int filedes, const char *mode)
+{
+  return do_fdopen (filedes, mode, 0);
+}
+
+/* A variant of es_fdopen which does not close FILEDES at the end.  */
+estream_t
+es_fdopen_nc (int filedes, const char *mode)
+{
+  return do_fdopen (filedes, mode, 1);
+}
+
+
+estream_t
+do_fpopen (FILE *fp, const char *mode, int no_close)
+{
+  unsigned int modeflags;
+  int create_called;
+  estream_t stream;
+  void *cookie;
+  int err;
+
+  stream = NULL;
+  cookie = NULL;
+  create_called = 0;
+
+  err = es_convert_mode (mode, &modeflags);
+  if (err)
+    goto out;
+
+  fflush (fp);
+  err = es_func_fp_create (&cookie, fp, modeflags, no_close);
+  if (err)
+    goto out;
+
+  create_called = 1;
+  err = es_create (&stream, cookie, fileno (fp), estream_functions_fp,
+                   modeflags);
+
+ out:
+
+  if (err && create_called)
+    (*estream_functions_fp.func_close) (cookie);
+
+  return stream;
+}
+
   
   
+/* Create an estream from the stdio stream FP.  This mechanism is
+   useful in case the stdio streams have special properties and may
+   not be mixed with fd based functions.  This is for example the case
+   under Windows where the 3 standard streams are associated with the
+   console whereas a duped and fd-opened stream of one of this stream
+   won't be associated with the console.  As this messes things up it
+   is easier to keep on using the standard I/O stream as a backend for
+   estream. */
+estream_t
+es_fpopen (FILE *fp, const char *mode)
+{
+  return do_fpopen (fp, mode, 0);
+}
+
+
+/* Same as es_fpopen but does not close  FP at the end.  */
+estream_t
+es_fpopen_nc (FILE *fp, const char *mode)
+{
+  return do_fpopen (fp, mode, 1);
+}
+
 
 estream_t
 es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
 
 estream_t
 es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
@@ -2009,7 +2222,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
 
   if (path)
     {
 
   if (path)
     {
-      unsigned int flags;
+      unsigned int modeflags;
       int create_called;
       void *cookie;
       int fd;
       int create_called;
       void *cookie;
       int fd;
@@ -2021,16 +2234,16 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
 
       es_deinitialize (stream);
 
 
       es_deinitialize (stream);
 
-      err = es_convert_mode (mode, &flags);
+      err = es_convert_mode (mode, &modeflags);
       if (err)
        goto leave;
       
       if (err)
        goto leave;
       
-      err = es_func_file_create (&cookie, &fd, path, flags);
+      err = es_func_file_create (&cookie, &fd, path, modeflags);
       if (err)
        goto leave;
 
       create_called = 1;
       if (err)
        goto leave;
 
       create_called = 1;
-      es_initialize (stream, cookie, fd, estream_functions_file);
+      es_initialize (stream, cookie, fd, estream_functions_file, modeflags);
 
     leave:
 
 
     leave:
 
@@ -2173,7 +2386,7 @@ es_fflush (estream_t stream)
   if (stream)
     {
       ESTREAM_LOCK (stream);
   if (stream)
     {
       ESTREAM_LOCK (stream);
-      if (stream->flags & ES_FLAG_WRITING)
+      if (stream->flags.writing)
        err = es_flush (stream);
       else
        {
        err = es_flush (stream);
       else
        {
@@ -2686,7 +2899,7 @@ tmpfd (void)
 estream_t
 es_tmpfile (void)
 {
 estream_t
 es_tmpfile (void)
 {
-  unsigned int flags;
+  unsigned int modeflags;
   int create_called;
   estream_t stream;
   void *cookie;
   int create_called;
   estream_t stream;
   void *cookie;
@@ -2695,7 +2908,7 @@ es_tmpfile (void)
 
   create_called = 0;
   stream = NULL;
 
   create_called = 0;
   stream = NULL;
-  flags = O_RDWR | O_TRUNC | O_CREAT;
+  modeflags = O_RDWR | O_TRUNC | O_CREAT;
   cookie = NULL;
   
   fd = tmpfd ();
   cookie = NULL;
   
   fd = tmpfd ();
@@ -2705,12 +2918,12 @@ es_tmpfile (void)
       goto out;
     }
 
       goto out;
     }
 
-  err = es_func_fd_create (&cookie, fd, flags);
+  err = es_func_fd_create (&cookie, fd, modeflags, 0);
   if (err)
     goto out;
 
   create_called = 1;
   if (err)
     goto out;
 
   create_called = 1;
-  err = es_create (&stream, cookie, fd, estream_functions_fd);
+  err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags);
 
  out:
 
 
  out:
 
index b569437..79bfbb7 100644 (file)
@@ -45,6 +45,9 @@
 #define es_mopen              _ESTREAM_PREFIX(es_mopen)
 #define es_open_memstream     _ESTREAM_PREFIX(es_open_memstream)
 #define es_fdopen             _ESTREAM_PREFIX(es_fdopen)
 #define es_mopen              _ESTREAM_PREFIX(es_mopen)
 #define es_open_memstream     _ESTREAM_PREFIX(es_open_memstream)
 #define es_fdopen             _ESTREAM_PREFIX(es_fdopen)
+#define es_fdopen_nc          _ESTREAM_PREFIX(es_fdopen_nc)
+#define es_fpopen             _ESTREAM_PREFIX(es_fpopen)
+#define es_fpopen_nc          _ESTREAM_PREFIX(es_fpopen_nc)
 #define es_freopen            _ESTREAM_PREFIX(es_freopen)
 #define es_fopencookie        _ESTREAM_PREFIX(es_fopencookie)
 #define es_fclose             _ESTREAM_PREFIX(es_fclose)
 #define es_freopen            _ESTREAM_PREFIX(es_freopen)
 #define es_fopencookie        _ESTREAM_PREFIX(es_fopencookie)
 #define es_fclose             _ESTREAM_PREFIX(es_fclose)
@@ -136,8 +139,10 @@ struct es__stream
   size_t unread_data_len;
 
   /* Various flags.  */
   size_t unread_data_len;
 
   /* Various flags.  */
-#define ES__FLAG_WRITING       (1 << 0)
-  unsigned int flags;
+  struct {
+    unsigned int writing: 1;
+    unsigned int reserved: 7;
+  } flags;
 
   /* A pointer to our internal data for this stream.  */
   struct estream_internal *intern;
 
   /* A pointer to our internal data for this stream.  */
   struct estream_internal *intern;
@@ -197,6 +202,9 @@ estream_t es_mopen (unsigned char *ES__RESTRICT data,
                    const char *ES__RESTRICT mode);
 estream_t es_open_memstream (char **ptr, size_t *size);
 estream_t es_fdopen (int filedes, const char *mode);
                    const char *ES__RESTRICT mode);
 estream_t es_open_memstream (char **ptr, size_t *size);
 estream_t es_fdopen (int filedes, const char *mode);
+estream_t es_fdopen_nc (int filedes, const char *mode);
+estream_t es_fpopen (FILE *fp, const char *mode);
+estream_t es_fpopen_nc (FILE *fp, const char *mode);
 estream_t es_freopen (const char *ES__RESTRICT path,
                      const char *ES__RESTRICT mode,
                      estream_t ES__RESTRICT stream);
 estream_t es_freopen (const char *ES__RESTRICT path,
                      const char *ES__RESTRICT mode,
                      estream_t ES__RESTRICT stream);
@@ -232,14 +240,14 @@ int _es_getc_underflow (estream_t stream);
 int _es_putc_overflow (int c, estream_t stream);
 
 #define es_getc_unlocked(stream)                               \
 int _es_putc_overflow (int c, estream_t stream);
 
 #define es_getc_unlocked(stream)                               \
-  (((! ((stream)->flags & 1))                                  \
+  (((!(stream)->flags.writing)                                 \
     && ((stream)->data_offset < (stream)->data_len)            \
     && (! (stream)->unread_data_len))                          \
   ? ((int) (stream)->buffer[((stream)->data_offset)++])                \
   : _es_getc_underflow ((stream)))
 
 #define es_putc_unlocked(c, stream)                            \
     && ((stream)->data_offset < (stream)->data_len)            \
     && (! (stream)->unread_data_len))                          \
   ? ((int) (stream)->buffer[((stream)->data_offset)++])                \
   : _es_getc_underflow ((stream)))
 
 #define es_putc_unlocked(c, stream)                            \
-  ((((stream)->flags & 1)                                      \
+  (((stream)->flags.writing                                    \
     && ((stream)->data_offset < (stream)->buffer_size)         \
     && (c != '\n'))                                            \
   ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c)))        \
     && ((stream)->data_offset < (stream)->buffer_size)         \
     && (c != '\n'))                                            \
   ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c)))        \
index 654c96b..e0c511c 100644 (file)
@@ -126,38 +126,10 @@ default_homedir (void)
 }
 
 
 }
 
 
-/* Return the name of the sysconfdir.  This is a static string.  This
-   function is required because under Windows we can't simply compile
-   it in.  */
-const char *
-gnupg_sysconfdir (void)
-{
 #ifdef HAVE_W32_SYSTEM
 #ifdef HAVE_W32_SYSTEM
-#warning get the sysconfdir from somewhere else
-  return GNUPG_SYSCONFDIR;
-#else /*!HAVE_W32_SYSTEM*/
-  return GNUPG_SYSCONFDIR;
-#endif /*!HAVE_W32_SYSTEM*/
-}
-
-
-const char *
-gnupg_bindir (void)
-{
-#ifdef HAVE_W32_SYSTEM
-  return gnupg_libexecdir ();
-#else /*!HAVE_W32_SYSTEM*/
-  return GNUPG_BINDIR;
-#endif /*!HAVE_W32_SYSTEM*/
-}
-
-
-/* Return the name of the libexec directory.  The name is allocated in
-   a static area on the first use.  This function won't fail. */
-const char *
-gnupg_libexecdir (void)
+static const char *
+w32_rootdir (void)
 {
 {
-#ifdef HAVE_W32_SYSTEM
   static int got_dir;
   static char dir[MAX_PATH+5];
 
   static int got_dir;
   static char dir[MAX_PATH+5];
 
@@ -184,17 +156,75 @@ gnupg_libexecdir (void)
   if (*dir)
     return dir;
   /* Fallback to the hardwired value. */
   if (*dir)
     return dir;
   /* Fallback to the hardwired value. */
+  return GNUPG_LIBEXECDIR;
+}
 #endif /*HAVE_W32_SYSTEM*/
 
 #endif /*HAVE_W32_SYSTEM*/
 
+
+
+
+/* Return the name of the sysconfdir.  This is a static string.  This
+   function is required because under Windows we can't simply compile
+   it in.  */
+const char *
+gnupg_sysconfdir (void)
+{
+#ifdef HAVE_W32_SYSTEM
+  static char *name;
+
+  if (!name)
+    {
+      const char *s1, *s2;
+      s1 = w32_rootdir ();
+      s2 = DIRSEP_S "etc" DIRSEP_S "gnupg";
+      name = xmalloc (strlen (s1) + strlen (s2) + 1);
+      strcpy (stpcpy (name, s1), s2);
+    }
+  return name;
+#else /*!HAVE_W32_SYSTEM*/
+  return GNUPG_SYSCONFDIR;
+#endif /*!HAVE_W32_SYSTEM*/
+}
+
+
+const char *
+gnupg_bindir (void)
+{
+#ifdef HAVE_W32_SYSTEM
+  return w32_rootdir ();
+#else /*!HAVE_W32_SYSTEM*/
+  return GNUPG_BINDIR;
+#endif /*!HAVE_W32_SYSTEM*/
+}
+
+
+/* Return the name of the libexec directory.  The name is allocated in
+   a static area on the first use.  This function won't fail. */
+const char *
+gnupg_libexecdir (void)
+{
+#ifdef HAVE_W32_SYSTEM
+  return w32_rootdir ();
+#else /*!HAVE_W32_SYSTEM*/
   return GNUPG_LIBEXECDIR;
   return GNUPG_LIBEXECDIR;
+#endif /*!HAVE_W32_SYSTEM*/
 }
 
 const char *
 gnupg_libdir (void)
 {
 #ifdef HAVE_W32_SYSTEM
 }
 
 const char *
 gnupg_libdir (void)
 {
 #ifdef HAVE_W32_SYSTEM
-#warning get the libdir from somewhere else
-  return GNUPG_LIBDIR;
+  static char *name;
+
+  if (!name)
+    {
+      const char *s1, *s2;
+      s1 = w32_rootdir ();
+      s2 = DIRSEP_S "lib" DIRSEP_S "gnupg";
+      name = xmalloc (strlen (s1) + strlen (s2) + 1);
+      strcpy (stpcpy (name, s1), s2);
+    }
+  return name;
 #else /*!HAVE_W32_SYSTEM*/
   return GNUPG_LIBDIR;
 #endif /*!HAVE_W32_SYSTEM*/
 #else /*!HAVE_W32_SYSTEM*/
   return GNUPG_LIBDIR;
 #endif /*!HAVE_W32_SYSTEM*/
@@ -204,8 +234,17 @@ const char *
 gnupg_datadir (void)
 {
 #ifdef HAVE_W32_SYSTEM
 gnupg_datadir (void)
 {
 #ifdef HAVE_W32_SYSTEM
-#warning get the datadir from somewhere else
-  return GNUPG_DATADIR;
+  static char *name;
+
+  if (!name)
+    {
+      const char *s1, *s2;
+      s1 = w32_rootdir ();
+      s2 = DIRSEP_S "share" DIRSEP_S "gnupg";
+      name = xmalloc (strlen (s1) + strlen (s2) + 1);
+      strcpy (stpcpy (name, s1), s2);
+    }
+  return name;
 #else /*!HAVE_W32_SYSTEM*/
   return GNUPG_DATADIR;
 #endif /*!HAVE_W32_SYSTEM*/
 #else /*!HAVE_W32_SYSTEM*/
   return GNUPG_DATADIR;
 #endif /*!HAVE_W32_SYSTEM*/
index 40af196..f395405 100644 (file)
@@ -40,6 +40,7 @@
 #endif /* __riscos__ */
 
 #include "util.h"
 #endif /* __riscos__ */
 
 #include "util.h"
+#include "sysutils.h"
 #include "iobuf.h"
 
 /* The size of the internal buffers. 
 #include "iobuf.h"
 
 /* The size of the internal buffers. 
@@ -2350,37 +2351,12 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
   return nbytes;
 }
 
   return nbytes;
 }
 
-/* This is the non iobuf specific function */
-int
-iobuf_translate_file_handle (int fd, int for_write)
-{
-#ifdef _WIN32
-  {
-    int x;
-
-    if (fd <= 2)
-      return fd;               /* do not do this for error, stdin, stdout, stderr */
-
-    x = _open_osfhandle (fd, for_write ? 1 : 0);
-    if (x == -1)
-      log_error ("failed to translate osfhandle %p\n", (void *) fd);
-    else
-      {
-       /*log_info ("_open_osfhandle %p yields %d%s\n",
-          (void*)fd, x, for_write? " for writing":"" ); */
-       fd = x;
-      }
-  }
-#endif
-  return fd;
-}
-
 static int
 translate_file_handle (int fd, int for_write)
 {
 #ifdef _WIN32
 #ifdef FILE_FILTER_USES_STDIO
 static int
 translate_file_handle (int fd, int for_write)
 {
 #ifdef _WIN32
 #ifdef FILE_FILTER_USES_STDIO
-  fd = iobuf_translate_file_handle (fd, for_write);
+  fd = translate_sys2libc_fd (fd, for_write);
 #else
   {
     int x;
 #else
   {
     int x;
index fa11f39..f20ea28 100644 (file)
@@ -136,8 +136,6 @@ const char *iobuf_get_fname (iobuf_t a);
 
 void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
 
 
 void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
 
-int iobuf_translate_file_handle (int fd, int for_write);
-
 void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial);
 
 
 void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial);
 
 
index ff1fe1b..a3fc8cb 100644 (file)
@@ -272,3 +272,32 @@ gnupg_sleep (unsigned int seconds)
 # endif
 #endif
 }
 # endif
 #endif
 }
+
+
+/* This function is a NOP for POSIX systems but required under Windows
+   as the file handles as returned by OS calls (like CreateFile) are
+   different from the libc file descriptors (like open). This function
+   translates system file handles to libc file handles.  FOR_WRITE
+   gives the direction of the handle.  */
+int
+translate_sys2libc_fd (int fd, int for_write)
+{
+#ifdef HAVE_W32_SYSTEM
+  int x;
+  
+  if (fd <= 2)
+    return fd; /* Do not do this for error, stdin, stdout, stderr.
+                   (This also ignores an fd of -1.) */
+
+  x = _open_osfhandle (fd, for_write ? 1 : 0);
+  if (x == -1)
+    log_error ("failed to translate osfhandle %p\n", (void *) fd);
+  else
+    {
+/*       log_info ("_open_osfhandle %p yields %d%s\n", */
+/*                 (void*)fd, x, for_write? " for writing":"" ); */
+      fd = x;
+    }
+#endif /* HAVE_W32_SYSTEM */
+  return fd;
+}
index 0e295f5..3ed702a 100644 (file)
@@ -28,6 +28,7 @@ int  enable_core_dumps (void);
 const unsigned char *get_session_marker (size_t *rlen);
 int check_permissions (const char *path,int extension,int checkonly);
 void gnupg_sleep (unsigned int seconds);
 const unsigned char *get_session_marker (size_t *rlen);
 int check_permissions (const char *path,int extension,int checkonly);
 void gnupg_sleep (unsigned int seconds);
+int translate_sys2libc_fd (int fd, int for_write);
 
 #ifdef HAVE_W32_SYSTEM
 
 
 #ifdef HAVE_W32_SYSTEM
 
index 27546e0..7123c5d 100644 (file)
@@ -1,3 +1,8 @@
+2007-06-22  Werner Koch  <wk@g10code.com>
+
+       * gpg.texi (Operational GPG Commands): Describe the flags used by
+       --check-sigs.
+
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * gpgsm.texi (Certificate Management): Changed description of
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * gpgsm.texi (Certificate Management): Changed description of
index b46036e..409320a 100644 (file)
@@ -309,6 +309,14 @@ command "tsign").
 @opindex check-sigs
 Same as @option{--list-sigs}, but the signatures are verified.
 
 @opindex check-sigs
 Same as @option{--list-sigs}, but the signatures are verified.
 
+The status of the verification is indicated by a flag directly following
+the "sig" tag (and thus before the flags described above for
+@option{--list-sigs}).  A "!" indicates that the signature has been
+successfully verified, a "-" denotes a bad signature and a "%" is used
+if an error occured while checking the signature (e.g. a non supported
+algorithm).
+
+
 @item --fingerprint
 @opindex fingerprint
 List all keys (or the specified ones) along with their
 @item --fingerprint
 @opindex fingerprint
 List all keys (or the specified ones) along with their
index e3db0f8..2958c9f 100644 (file)
@@ -1,3 +1,9 @@
+2007-06-25  Werner Koch  <wk@g10code.com>
+
+       * gpg.c (main): Replace iobuf_translate_file_handle by
+       translate_sys2libc_fd.
+       * gpgv.c (main): Ditto.
+
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * main.h: Include util.h.
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * main.h: Include util.h.
index 44ea804..d1d79ea 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2161,19 +2161,19 @@ main (int argc, char **argv )
           case oDebugLevel: debug_level = pargs.r.ret_str; break;
 
          case oStatusFD:
           case oDebugLevel: debug_level = pargs.r.ret_str; break;
 
          case oStatusFD:
-            set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) );
+            set_status_fd( translate_sys2libc_fd (pargs.r.ret_int, 1) );
             break;
          case oStatusFile:
             set_status_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oAttributeFD:
             break;
          case oStatusFile:
             set_status_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oAttributeFD:
-            set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            set_attrib_fd(translate_sys2libc_fd (pargs.r.ret_int, 1));
             break;
          case oAttributeFile:
             set_attrib_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oLoggerFD:
             break;
          case oAttributeFile:
             set_attrib_fd ( open_info_file (pargs.r.ret_str, 1) );
             break;
          case oLoggerFD:
-            log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            log_set_fd (translate_sys2libc_fd (pargs.r.ret_int, 1));
             break;
           case oLoggerFile:
             logfile = pargs.r.ret_str;
             break;
           case oLoggerFile:
             logfile = pargs.r.ret_str;
@@ -2437,14 +2437,14 @@ main (int argc, char **argv )
            set_passphrase_from_string(pargs.r.ret_str);
            break;
          case oPasswdFD:
            set_passphrase_from_string(pargs.r.ret_str);
            break;
          case oPasswdFD:
-            pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
+            pwfd = translate_sys2libc_fd (pargs.r.ret_int, 0);
             break;
          case oPasswdFile:
             pwfd = open_info_file (pargs.r.ret_str, 0);
             break;
          case oPasswdRepeat: opt.passwd_repeat=pargs.r.ret_int; break;
          case oCommandFD:
             break;
          case oPasswdFile:
             pwfd = open_info_file (pargs.r.ret_str, 0);
             break;
          case oPasswdRepeat: opt.passwd_repeat=pargs.r.ret_int; break;
          case oCommandFD:
-            opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
+            opt.command_fd = translate_sys2libc_fd (pargs.r.ret_int, 0);
             break;
          case oCommandFile:
             opt.command_fd = open_info_file (pargs.r.ret_str, 0);
             break;
          case oCommandFile:
             opt.command_fd = open_info_file (pargs.r.ret_str, 0);
index 73f3be0..f7cac34 100644 (file)
@@ -155,7 +155,7 @@ main( int argc, char **argv )
           case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
          case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
          case oLoggerFD: 
           case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
          case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
          case oLoggerFD: 
-            log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1));
+            log_set_fd (translate_sys2libc_fd (pargs.r.ret_int, 1));
             break;
          case oHomedir: opt.homedir = pargs.r.ret_str; break;
          case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
             break;
          case oHomedir: opt.homedir = pargs.r.ret_str; break;
          case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
index 737a57d..a57af3c 100644 (file)
@@ -1,3 +1,13 @@
+2007-06-25  Werner Koch  <wk@g10code.com>
+
+       * gpgsm.c (check_special_filename): Use translate_sys2libc_fd and
+       add new arg FOR_WRITE.  Change callers to pass new arg.
+
+2007-06-24  Werner Koch  <wk@g10code.com>
+
+       * gpgsm.c (open_es_fwrite): Avoid the dup by using the new
+       es_fdopen_nc().  
+
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * certreqgen-ui.c: New.
 2007-06-21  Werner Koch  <wk@g10code.com>
 
        * certreqgen-ui.c: New.
index 4ffd836..bb30a63 100644 (file)
@@ -573,8 +573,8 @@ proc_parameters (ctrl_t ctrl,
       if (rc)
         {
           r = get_parameter (para, pKEYTYPE, 0);
       if (rc)
         {
           r = get_parameter (para, pKEYTYPE, 0);
-          log_error (_("line %d: key generation failed: %s\n"),
-                     r->lnr, gpg_strerror (rc));
+          log_error (_("line %d: key generation failed: %s <%s>\n"),
+                     r->lnr, gpg_strerror (rc), gpg_strsource (rc));
           xfree (cardkeyid);
           return rc;
         }
           xfree (cardkeyid);
           return rc;
         }
@@ -863,8 +863,8 @@ gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *in_stream, FILE *out_fp)
   rc = read_parameters (ctrl, in_fp, writer);
   if (rc)
     {
   rc = read_parameters (ctrl, in_fp, writer);
   if (rc)
     {
-      log_error ("error creating certificate request: %s\n",
-                 gpg_strerror (rc));
+      log_error ("error creating certificate request: %s <%s>\n",
+                 gpg_strerror (rc), gpg_strsource (rc));
       goto leave;
     }
 
       goto leave;
     }
 
index ee6cf08..d3be015 100644 (file)
@@ -481,7 +481,7 @@ static void set_cmd (enum cmd_and_opt_values *ret_cmd,
                      enum cmd_and_opt_values new_cmd );
 
 static void emergency_cleanup (void);
                      enum cmd_and_opt_values new_cmd );
 
 static void emergency_cleanup (void);
-static int check_special_filename (const char *fname);
+static int check_special_filename (const char *fname, int for_write);
 static int open_read (const char *filename);
 static FILE *open_fwrite (const char *filename);
 static estream_t open_es_fwrite (const char *filename);
 static int open_read (const char *filename);
 static FILE *open_fwrite (const char *filename);
 static estream_t open_es_fwrite (const char *filename);
@@ -1732,7 +1732,7 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
 /* Check whether the filename has the form "-&nnnn", where n is a
    non-zero number.  Returns this number or -1 if it is not the case.  */
 static int
 /* Check whether the filename has the form "-&nnnn", where n is a
    non-zero number.  Returns this number or -1 if it is not the case.  */
 static int
-check_special_filename (const char *fname)
+check_special_filename (const char *fname, int for_write)
 {
   if (allow_special_filenames
       && fname && *fname == '-' && fname[1] == '&' ) {
 {
   if (allow_special_filenames
       && fname && *fname == '-' && fname[1] == '&' ) {
@@ -1742,7 +1742,7 @@ check_special_filename (const char *fname)
     for (i=0; isdigit (fname[i]); i++ )
       ;
     if ( !fname[i] ) 
     for (i=0; isdigit (fname[i]); i++ )
       ;
     if ( !fname[i] ) 
-      return atoi (fname);
+      return translate_sys2libc_fd (atoi (fname), for_write);
   }
   return -1;
 }
   }
   return -1;
 }
@@ -1762,7 +1762,7 @@ open_read (const char *filename)
       set_binary (stdin);
       return 0; /* stdin */
     }
       set_binary (stdin);
       return 0; /* stdin */
     }
-  fd = check_special_filename (filename);
+  fd = check_special_filename (filename, 0);
   if (fd != -1)
     return fd;
   fd = open (filename, O_RDONLY | O_BINARY);
   if (fd != -1)
     return fd;
   fd = open (filename, O_RDONLY | O_BINARY);
@@ -1790,7 +1790,7 @@ open_fwrite (const char *filename)
       return stdout;
     }
 
       return stdout;
     }
 
-  fd = check_special_filename (filename);
+  fd = check_special_filename (filename, 1);
   if (fd != -1)
     {
       fp = fdopen (dup (fd), "wb");
   if (fd != -1)
     {
       fp = fdopen (dup (fd), "wb");
@@ -1825,14 +1825,14 @@ open_es_fwrite (const char *filename)
   if (filename[0] == '-' && !filename[1])
     {
       fflush (stdout);
   if (filename[0] == '-' && !filename[1])
     {
       fflush (stdout);
-      fp = es_fdopen (dup (fileno(stdout)), "wb");
+      fp = es_fdopen_nc (fileno(stdout), "wb");
       return fp;
     }
 
       return fp;
     }
 
-  fd = check_special_filename (filename);
+  fd = check_special_filename (filename, 1);
   if (fd != -1)
     {
   if (fd != -1)
     {
-      fp = es_fdopen (dup (fd), "wb");
+      fp = es_fdopen_nc (fd, "wb");
       if (!fp)
         {
           log_error ("es_fdopen(%d) failed: %s\n", fd, strerror (errno));
       if (!fp)
         {
           log_error ("es_fdopen(%d) failed: %s\n", fd, strerror (errno));