Hi Paul,

> When I run a long command, e.g.
> 
> pdptest aaaaaaaaaaaaaaaa ... (to exceed 126
> characters), and it is a Win32 executable so HX
> gets involved, I get a crash.

You write that Japheth writes:

> IMO it's a bug in FD command.com. If a command
> line exceeds 126 bytes, the value at [PSP:80h]
> "should" be 0x7Fh ( and a 0x0D "should" be placed
> at [PSP:FFh] ) - that's at least what COMMAND.COM
> of Win95/98 does. The environment variable
> CMDLINE will then contain the full command line.
> It's documented in RBIL.

In FreeCOM, MAX_EXTERNAL_COMMAND_SIZE is 125, because
for normal command lines, psp_cmdlineLength is max that,
followed by psp_cmdline with trailing \r AND \0 chars.

Note that FreeCOM unfortunately never uses psp_... so
the code is harder to read.

Now when you have a LONG command line, two areas of
the C code become relevant:

shell/init.c is what received the command line when
you start a new instance of FreeCOM, which probably
is what HX does to start a Windows program, although
I am not sure why it does it like that.

https://github.com/FDOS/freecom/blob/master/shell/init.c

int initialize(void)
{
...
  /* Aquire the command line, there are three possible sources:
    1) DOS command line @PSP:0x80 as pascal string,
    2) extended DOS command line environment variable CMDLINE,
      if peekb(PSP, 0x80) == 127,&
    3) MKS command line @ENV:2, if peekb(ENV, 0) == '~'
        && peekb(ENV, 1) == '='

    Currently implemented is version #1 only
  */
  cmdlen = peekb(_psp, 0x80);
  if(cmdlen < 0 || cmdlen > 126) {
    error_corrupt_command_line();
    cmdlen = 0;
  }
...

This would show, if you are using the English version:

Corrupt command line. This is an internal error and is related to
the system COMMAND.COM runs in. Please report this error.

The other part is that when you already have FreeCOM running
and want to execute some other app, via lib/exec.c

https://github.com/FDOS/freecom/blob/master/lib/exec.c

int exec(const char *cmd, char *cmdLine, const unsigned segOfEnv)
{
...
  assert(cmd);
  assert(cmdLine);
  assert(strlen(cmdLine) <= 125);
...

as well as shell/command.c, bad indent caused by tab size 8
in my viewer while apparently the file assumes tab size 4:

https://github.com/FDOS/freecom/blob/master/shell/command.c

void execute(char *first, char *rest, int lh_lf)
{
...
        if(strlen(rest) > MAX_EXTERNAL_COMMAND_SIZE) {
        char *fullcommandline = malloc( strlen( first ) + strlen( rest )
+ 2 );
        error_line_too_long();
        if( fullcommandline == NULL ) return;
        sprintf( fullcommandline, "%s%s", first, rest );
        if( chgEnv( "CMDLINE", fullcommandline ) != 0 ) {
            free( fullcommandline );
            return;
        }
        free( fullcommandline );
        }
...

This displays "Commandline longer than 125 characters."
and leaves it up to the user to wonder whether that is
a problem. Actually it cannot know which apps support
long command lines, so thata probably is OK.

Also note: CMDLINE is only used for com and exe, not for bat.

Unfortunately, the above part is the ONLY place which uses
MAX_EXTERNAL_COMMAND_SIZE, while the assert above hardcodes
125 and init.c hardcodes "negative or above 126" and fails
to to anything about long command line used when it is
started with one itself, by some outside caller.

shell/cswapc.c contains this:

https://github.com/FDOS/freecom/blob/master/shell/cswapc.c

DoExec(char *command,char *cmdtail)
{
...
        len = strlen(cmdtail);
        if (len >= 127) len = 127; SEE BELOW
        dosCMDTAIL[0] = len;
        dosCMDTAIL[1+ len] = '\r';
...

Because dosCMDTAIL is ((char far*)MK_FP(_psp, 0x80))
this would actually overflow the buffer by 1 byte :-p

Japheth's description implies that 127 has to be used
as magic length, together with injecting an early \r
into the PSP and not bothering to put an \0 after it.

So proper code without long command line support was,
only changing the SEE BELOW line:

if (len > MAX_EXTERNAL_COMMAND_SIZE) len = 126;

But proper code for long command line support would
make a case distinction for long versus short lines.

Note that the assembly language parts of FreeCOM do
not process long command lines at all, they simply
assume that the C parts have already limited the PSP
command line in a sensible way and do not care whether
or not the environment contains any CMDLINE variable.
This probably is OK.

You could probably change SHELL or COMSPEC to let HX use
for example DJGPP BASH instead of FreeCOM to see whether
HX itself works okay, but that will have big side effects
and BASH does not use the same "command.com /C command"
style syntax as command.com, while /C likely is hardcoded
into HX when it invokes programs.

In short, the CMDLINE support of FreeCOM looks sketchy
at best, in spite of having been added at 0.84pre7 and
me looking at https://github.com/FDOS/freecom today,
not 17 months ago when CHANGED got the 0.84-pre7 info.

Jeremy and Bart seem to be preparing a version bump to
"FreeCom version 0.85 - WATCOMC [May 31 2021]" right
now. I hope they will include CMDLINE fixes before that!

Regards, Eric



_______________________________________________
Freedos-user mailing list
Freedos-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freedos-user

Reply via email to