Mail Archives: djgpp/1999/04/05/17:49:27
On Fri, 2 Apr 1999, Tim Updegrove wrote:
> A simple REDIR command like "redir -o gcc.log gcc -v -o hello.exe
> hello.c" puts "bad command or file name" in gcc.log. A user on
> 2/24/99 had this same problem in the mail archives (see Re: Beginners
> help/problem) and his root cause was no swap memory in DOS window.
> This very well may be my problem because I'm running in a DOS window
> in Win95.
Thanks for reporting this.
This has nothing to do with swap space, this is simply a very subtle
bug in the version of REDIR distributed with v2.02. Sorry, it's
entirely my fault: not only did I introduce this bug, I also managed
to conceal it so well that the resulting code worked 99.99% of time,
and needed special file names to raise its ugly head. Which explains
how I missed it, all my testing notwithstanding...
To work around the bug, make sure the files to where you redirect
input/output (like `gcc.log' in the case above) don't have the command
(`gcc' in this case) as their substring, and then the bug won't
happen. It also only affects `redir' invocations from the DOS prompt,
so Makefiles which use `redir' are safe. The problem also doesn't
happen when `redir' is invoked from another DJGPP program, so Bash
users will never see it.
I have a corrected version of `redir.exe', so people who have these
problems and need a replacement, please mail me privately. Those who
have sources (djlsr202.zip) can apply the patch below and rebuild
`redir.exe' (there's no need to rebuild the whole library, simply
extract redir.c and type "gcc -Wall -O2 -o redir.exe redir.c").
The corrected version will go into the next release of DJGPP.
*** src/utils/redir.c~0 Sun Nov 15 13:55:44 1998
--- src/utils/redir.c Sun Apr 4 20:52:08 1999
***************
*** 1,8 ****
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*
! Redir 2.0 Copyright (C) 1995-1998 DJ Delorie (dj AT delorie DOT com)
Redir is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
--- 1,9 ----
+ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*
! Redir 2.1 Copyright (C) 1995-1999 DJ Delorie (dj AT delorie DOT com)
Redir is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
*************** static void
*** 66,72 ****
usage(void)
{
/* ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8 */
! fprintf(stderr, "Redir 2.0 Copyright (C) 1995 - 1998 DJ Delorie (dj AT delorie DOT com)\n");
fprintf(stderr, "Distribute freely. There is NO WARRANTY.\n");
fprintf(stderr, "This program is protected by the GNU General Public License.\n\n");
fprintf(stderr, "Usage: redir [-i file] [-o file] [-oa file] [-e file] [-ea file]\n");
--- 67,73 ----
usage(void)
{
/* ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8 */
! fprintf(stderr, "Redir 2.1 Copyright (C) 1995 - 1999 DJ Delorie (dj AT delorie DOT com)\n");
fprintf(stderr, "Distribute freely. There is NO WARRANTY.\n");
fprintf(stderr, "This program is protected by the GNU General Public License.\n\n");
fprintf(stderr, "Usage: redir [-i file] [-o file] [-oa file] [-e file] [-ea file]\n");
*************** extern char __PROXY[]; /* defined on crt
*** 140,146 ****
extern size_t __PROXY_LEN;
static int
! run_program(int argc, char *argv[])
{
char doscmd[128];
char *tail = doscmd + 1, *tp = tail;
--- 141,147 ----
extern size_t __PROXY_LEN;
static int
! run_program(int argc, char *argv[], int skip)
{
char doscmd[128];
char *tail = doscmd + 1, *tp = tail;
*************** run_program(int argc, char *argv[])
*** 175,199 ****
if (++i == 3)
{
gettimeofday(&startt, NULL);
! return spawnvp(P_WAIT, argv[1], argv+1);
}
} while (*endarg);
}
}
/* The DOS command tail is the actual command line.
Get past our own options we've already parsed,
! and pass the rest to the child via `system'. */
! tail = strstr(tail, argv[1]);
! gettimeofday(&startt, NULL);
! return system(tail);
}
/* We need to recreate the original command line as a single string,
from its breakdown in argv[]. */
! for (tail_len = 0, i = 1; i < argc; i++)
tail_len += strlen(argv[i]) + 1; /* +1 for the blank between args */
tp = tail = (char *)xmalloc(tail_len + 1);
! for (i = 1; i < argc; i++)
{
size_t len = strlen(argv[i]);
memcpy(tp, argv[i], len);
--- 176,215 ----
if (++i == 3)
{
gettimeofday(&startt, NULL);
! return spawnvp(P_WAIT, argv[skip], argv+skip);
}
} while (*endarg);
}
}
/* The DOS command tail is the actual command line.
Get past our own options we've already parsed,
! and pass the rest to the child via `system'.
! SKIP says how many argv[] elements to skip. */
! for (tp = tail; skip--; argv++)
! {
! tp = strstr(tp, argv[1]);
! /* If, at some point, we don't find the next argv[] element,
! it's probably some disaster, because they all should be
! there. Instead of screaming bloody murder, we fall back
! on using argv[] from our `main', as the last resort. */
! if (!tp)
! break;
! if (skip == 0)
! {
! /* We've come all the way to the child command line, invoke it. */
! gettimeofday(&startt, NULL);
! return system(tp);
! }
! tp += strlen(argv[1]); /* get past this arg */
! }
}
/* We need to recreate the original command line as a single string,
from its breakdown in argv[]. */
! for (tail_len = 0, i = skip; i < argc; i++)
tail_len += strlen(argv[i]) + 1; /* +1 for the blank between args */
tp = tail = (char *)xmalloc(tail_len + 1);
! for (i = skip; i < argc; i++)
{
size_t len = strlen(argv[i]);
memcpy(tp, argv[i], len);
*************** int
*** 210,215 ****
--- 226,233 ----
main(int argc, char **argv)
{
char *arg1 = NULL, *arg2 = NULL;
+ int ac = argc;
+ char **av = argv;
/* Don't let us crash because some naughty program left
the FPU in shambles. */
*************** main(int argc, char **argv)
*** 312,318 ****
or crashes for any reason. */
_control87(0x033f, 0xffff); /* mask all numeric exceptions */
__djgpp_exception_toggle();
! rv = run_program(argc, argv);
gettimeofday(&endt, NULL);
_clear87(); /* clean up after the child, just in case */
_fpreset();
--- 330,336 ----
or crashes for any reason. */
_control87(0x033f, 0xffff); /* mask all numeric exceptions */
__djgpp_exception_toggle();
! rv = run_program(ac, av, ac - argc + 1);
gettimeofday(&endt, NULL);
_clear87(); /* clean up after the child, just in case */
_fpreset();
- Raw text -