Building sharutils 4.13.4 with MinGW

Eli Zaretskii <[email protected]>
Newsgroups gmane.comp.gnu.utils.bugs
Message-ID <[email protected]>
I've built this distribution with MinGW tools on MS-Windows.  Quite
unexpectedly for such a veteran package, it turned out to be an uphill
battle.

In addition to MinGW-specific issues (which I will describe in a
separate message), I found a few issues that could show up on other
systems:

1. configure errors out:

     configure: error: you must have sys_mman.h on your system

   This is because libopts/m4/libopts.m4 does this:

     for f in sys_types sys_mman sys_param sys_stat sys_wait \
	      string errno stdlib memory setjmp
     do eval as_ac_var=\${ac_cv_header_${f}_h}
	test "X${as_ac_var}" = Xyes || {
	  ]AC_MSG_ERROR([you must have ${f}.h on your system])[
	}
     done

   I don't understand why configure insists on having sys/mman.h and
   sys/wait.h, because the code has appropriate fallbacks for when
   they are not present.  My solution was to remove sys_mman and
   sys_wait from the above list.

2. There's a bug in text_mmap.c (in the part that falls back to
   reading a file if mmap is unavailable): the txt_zero_fd member of
   tmap_info_t structure was not initialized to -1, so stayed at zero
   and was closed (twice) by close_mmap_files, which caused an invalid
   argument debug message from the runtime library.

   My solution was this:

--- sharutils-4.13.4.orig/libopts/text_mmap.c	2013-03-31 19:56:09.000000000 +0300
+++ sharutils-4.13.4/libopts/text_mmap.c	2013-04-04 16:30:08.429263900 +0300
@@ -233,7 +233,7 @@ close_mmap_files(tmap_info_t * mi)
     close(mi->txt_fd);
     mi->txt_fd = AO_INVALID_FD;
 
-#if ! defined(MAP_ANONYMOUS)
+#if defined(HAVE_MMAP) && ! defined(MAP_ANONYMOUS)
     if (mi->txt_zero_fd == AO_INVALID_FD)
         return;
 
3. Using the -R option seems to bypass encoding and only records the
   options to the RC file -- is that intended?  If so, it seems to be
   undocumented (I initially thought it was a bug, and only by
   stepping through the code found out that uudecode -R simply exits
   after outputting the options to the RC file).

4. When passed 2 or more base64-encoded files, uudecode barfs on the
   second one:

     d:\usr\eli\utils\sharutils-4.13.4>src\uudecode bar2.b64 bar3.b64
     uudecode fatal error:
     bar3.b64: Invalid or missing 'begin' line

   This is because of the following snippet in decode:

      if (strncmp (buf, "begin", 5) == 0)
	{
          char * scan = buf+5;
          if (*scan == '-')
            {
              static char const base64[]  = "ase64";
              static char const encoded[] = "encoded";
            check_begin_option:
              if (*++scan == 'b')
                {
                  if (strncmp (scan+1, base64, sizeof (base64) - 1) != 0)
                    goto bad_beginning;
                  if (do_base64)
                    goto bad_beginning;  <<<<<<<<<<<<<<<<<<<<<<<
                  do_base64 = true;
                  scan += sizeof (base64); /* chars + 'b' */

   do_base64 is a static variable that doesn't get reset after
   processing each file.

   My solution was to reset do_base64 after each file finishes
   processing:

--- sharutils-4.13.4.orig/src/uudecode.c	2013-03-29 17:28:40.000000000 +0300
+++ sharutils-4.13.4/src/uudecode.c	2013-04-07 09:38:10.818181900 +0300
@@ -497,6 +518,7 @@ multiple input files.\n"));
               error (0, errno, "%s", f);
               exit_status |= UUDECODE_EXIT_NO_INPUT;
             }
+          do_base64 = false;
         }
     }


5. Question: can /dev/stdout or - appear on the encoded file's begin
   line?  If it can, then processing several files when one of them
   has such a line will not redirect output back to the original
   stream, because this snippet:

     if (  (strcmp (outname, "/dev/stdout") != 0)
	&& (strcmp (outname, "-") != 0) )
       {
	 rval = reopen_output (outname, mode);
	 if (rval != UUDECODE_EXIT_SUCCESS)
	   goto fail_return;
       }

   doesn't redirect stdout in that case.  So it looks like uudecode
   will continue writing to the previously decoded file, instead of
   resetting stdout to the original stream/descriptor.

6. shar fails to record the time and the submitter of the archive:

     # Made on  by <>.

   The time was missing because print_header_stamp assumed %Z format
   in strftime always takes at most 4 characters:

     static char const ftime_fmt[] = "%Y-%m-%d %H:%M %Z";
     /*
      * All fields are two characters, except %Y is four.
      */
     char buffer[sizeof (ftime_fmt) + 4]; <<<<<<<<<<<<<<<
     time_t now;
     struct tm * local_time;
     time (&now);
     local_time = localtime (&now);
     strftime (buffer, sizeof (buffer) - 1, ftime_fmt, local_time);

   which is false on Windows; the code was not testing the return
   value of strftime, so it didn't see the falure.

   My solution was to reallocate the buffer if strftime returns zero:

--- sharutils-4.13.4.orig/src/shar.c	2013-03-23 00:23:48.000000000 +0200
+++ sharutils-4.13.4/src/shar.c	2013-04-07 13:41:14.742531000 +0300
@@ -916,13 +921,20 @@ print_header_stamp (FILE * fp)
     static char const ftime_fmt[] = "%Y-%m-%d %H:%M %Z";
     /*
      * All fields are two characters, except %Y is four.
+     * The length of %Z is implementation-defined.
      */
-    char buffer[sizeof (ftime_fmt) + 4];
+    size_t bsize = sizeof (ftime_fmt) + 4;
+    char *buffer = alloca (bsize);
     time_t now;
     struct tm * local_time;
+    size_t len;
     time (&now);
     local_time = localtime (&now);
-    strftime (buffer, sizeof (buffer) - 1, ftime_fmt, local_time);
+    while ((len = strftime (buffer, bsize - 1, ftime_fmt, local_time)) == 0)
+      {
+        bsize += 40;
+        buffer = alloca (bsize);
+      }
     fprintf (fp, made_on_comment_z, buffer, OPT_ARG(SUBMITTER));
   }
 
   The problem with submitter was because set_submitter assigned a
   local buffer to the submitter option argument, without using
   xstrdup:

     static void
     set_submitter (void)
     {
       char buffer[256];  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
       char * uname = getuser (getuid ());
       size_t len   = strlen (uname);
       if (uname == NULL)
	 fserr (SHAR_EXIT_FAILED, "getpwuid", "getuid()");

       memcpy (buffer, uname, len);
       buffer[len++] = '@';
       gethostname (buffer + len, sizeof (buffer) - len);
       SET_OPT_SUBMITTER(buffer);  <<<<<<<<<<<<<<<<<<<<<<<<<
     }

   Solution: use xstrdup inside the SET_OPT_SUBMITTER call.

HTH

P.S.  I'm not subscribed to this list, so please CC me on the
responses.

P.P.S.  Thanks for maintaining sharutils!
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.