www.delorie.com/djgpp/bugs/show.cgi   search  
Bug 000153

When Created: 05/15/1997 22:00:54
Against DJGPP version: 2.01
By whom: fighteer@cs.com
Abstract: redir passes wildcards incorrectly to child program
There's a bug in the code for redir from DJGPP v2.01 that causes wildcards on
the command line to be passed incorrectly to child programs.  For example, the
following command line:

redir -e err.log rm *.o

will produce:

rm: *.o: No such file or directory (ENOENT)

This problem first appeared in v2.01.

Solution added: 05/15/1997 22:16:50
By whom: fighteer@cs.com
The problem lies in the enhanced command line handling of the v2.01 libc.  redir
uses spawnvp() to pass command lines, but v2.01 programs do not perform wildcard
expansion on command lines received via spawn*().  Since redir does not perform
wildcard expansion itself, this caused command lines to be passed verbatim instead
of being expanded by the child program.

The solution is to switch spawnvp() in redir.c with system().  This also requires
that redir reconstruct the original command line.  The required patch is below;
I also modified the makefile for redir to increase the default transfer buffer
size, since redir could conceivably fail when passed extremely long command lines.

*** src/utils/redir.c~0	Wed Jul 12 04:06:50 1995
--- src/utils/redir.c	Thu May 15 22:09:28 1997
***************
*** 46,55 ****
  {
    /*               ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8 */
    fprintf(stderr, "Redir 1.0 Copyright (C) 1995 DJ Delorie (dj@delorie.com) - distribute freely\n");
!   fprintf(stderr, "NO WARRANTEE.  This program is protected by the GNU General Public License.\n");
    fprintf(stderr, "Usage: redir [-i file] [-o file] [-oa file] [-e file] [-ea file]\n");
    fprintf(stderr, "                [-eo] [-oe] [-x] [-t] command [args . . .]
\n");
!   fprintf(stderr, "  -i file   redirect stdandard input from file\n");
    fprintf(stderr, "  -o file   redirect standard output to file\n");
    fprintf(stderr, "  -oa file  append standard output to file\n");
    fprintf(stderr, "  -e file   redirect standard error to file\n");
--- 46,55 ----
  {
    /*               ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8 */
    fprintf(stderr, "Redir 1.0 Copyright (C) 1995 DJ Delorie (dj@delorie.com) - distribute freely\n");
!   fprintf(stderr, "NO WARRANTY.  This program is protected by the GNU General Public License.\n");
    fprintf(stderr, "Usage: redir [-i file] [-o file] [-oa file] [-e file] [-ea file]\n");
    fprintf(stderr, "                [-eo] [-oe] [-x] [-t] command [args . . .]
\n");
!   fprintf(stderr, "  -i file   redirect standard input from file\n");
    fprintf(stderr, "  -o file   redirect standard output to file\n");
    fprintf(stderr, "  -oa file  append standard output to file\n");
    fprintf(stderr, "  -e file   redirect standard error to file\n");
***************
*** 74,79 ****
--- 74,82 ----
  int
  main(int argc, char **argv)
  {
+   char *cmdline;  /* hold command line to pass to system() */
+   size_t sz;      /* size of allocation for cmdline */
+   int i;          /* arg counter */
  
    if (argc < 2)
      usage();
***************
*** 151,157 ****
      argv++;
    }
  
!   rv = spawnvp(P_WAIT, argv[1], argv+1);
    if (rv < 0)
      fatal("Error attempting to run program %s\n", argv[1]);
  
--- 154,188 ----
      argv++;
    }
  
!   /* The old method of calling spawnvp() breaks v2.01 programs that use
!    * wildcards.  To fix this, build the remaining arguments into one long
!    * string to pass to system().
!    */
!   sz = 16384;   /* initial malloc size */
!   if ((cmdline = malloc(sz)) == NULL)
!   {
!     fprintf(std_err, "redir: malloc failed for %lu bytes", sz);
!     exit(1);
!   }
!   *cmdline = '\0';
!   for (i = 1; i < argc; i++)
!   {
!     if (strlen(cmdline) + strlen(argv[i]) + 1 > sz)
!     {
!       sz += 16384;   /* malloc increment */
!       if ((cmdline = realloc(cmdline,sz)) == NULL)
!       {
! 	fprintf(std_err, "redir: realloc failed for %lu bytes", sz);
! 	exit(1);
!       }
!     }
!     strcat(cmdline, argv[i]);
!     if (i < argc - 1)
! 	strcat(cmdline, " ");
!   }
!   rv = system(cmdline);
!   free(cmdline);
!   
    if (rv < 0)
      fatal("Error attempting to run program %s\n", argv[1]);
  
*** src/utils/makefile.~	Tue Jan 23 22:15:58 1996
--- src/utils/makefile	Thu Feb 20 19:02:46 1997
***************
*** 21,26 ****
--- 21,31 ----
  
  include $(TOP)/../makefile.prg
  
+ $(BIN)/redir.exe : $C redir.o $L
+ 	$(LINK)
+ 	$(EXE)
+ 	$(BIN)/stubedit $(BIN)/redir.exe bufsize=64k
+ 
  $(BIN)/rem.com : rem.asm
  	djasm $^ $@
  

Solution added: 04/12/1999 11:00:22
By whom: eliz@is.elta.co.il
The correct solution is not to call `system', it is much more complex.
See the sources of v2.02 and later for how this is fixed.

Fixed in version on 04/12/1999 11:00:45
By whom: eliz@is.elta.co.il



  webmaster   donations   bookstore     delorie software   privacy  
  Copyright 2010   by DJ Delorie     Updated Jul 2010