Date: Mon, 5 Apr 1999 08:15:25 +0200 (IST) From: Eli Zaretskii X-Sender: eliz AT is To: Tim Updegrove cc: djgpp AT delorie DOT com, djgpp-workers AT delorie DOT com Subject: Re: REDIR - Bad command or file name In-Reply-To: <370519a3.4299122@news.enter.net> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Reply-To: djgpp-workers AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk 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();