And just to add to the fun, CP/M, MS-DOS and then Windows NT all copied
the basic DEC-style command line architecture, while neglecting the
crucial part of a built-in command parser to handle more sophisticated >syntax. So Microsoft’s recent rediscovery that “the command line is cool”
remains hampered by this brain-dead underlying architecture.
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
And just to add to the fun, CP/M, MS-DOS and then Windows NT all copied
the basic DEC-style command line architecture, while neglecting the
crucial part of a built-in command parser to handle more sophisticated
syntax. So Microsoft’s recent rediscovery that “the command line is cool”
remains hampered by this brain-dead underlying architecture.
To give them credit, Microsoft finally realized that command.com was
hopeless and started from first principles with Powershell. Powershell
is easily as good as anything DEC had in 1974 and as such is a huge
advance for the desktop.
On 5/23/2024 6:19 AM, Scott Dorsey wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
And just to add to the fun, CP/M, MS-DOS and then Windows NT all
copied the basic DEC-style command line architecture, while
neglecting the crucial part of a built-in command parser to handle
more sophisticated syntax. So Microsoft’s recent rediscovery that
“the command line is cool” remains hampered by this brain-dead
underlying architecture.
To give them credit, Microsoft finally realized that command.com was hopeless and started from first principles with Powershell.
Powershell is easily as good as anything DEC had in 1974 and as
such is a huge advance for the desktop.
Just so that everyone know the history:
command.com - 1980
cmd.exe - 1987 (backwards compatible with command.com, but
significantly extended functionality, often via obscure syntax though)
Windows Script Host / VBScript - 1995 (not interactive, scripts only,
but very powerful via WMI)
PowerShell - 2006
Not super new.
:-)
Arne
On Thu, 23 May 2024 09:28:16 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/23/2024 6:19 AM, Scott Dorsey wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
And just to add to the fun, CP/M, MS-DOS and then Windows NT all
copied the basic DEC-style command line architecture, while
neglecting the crucial part of a built-in command parser to handle
more sophisticated syntax. So Microsoft’s recent rediscovery that
“the command line is cool” remains hampered by this brain-dead
underlying architecture.
To give them credit, Microsoft finally realized that command.com was
hopeless and started from first principles with Powershell.
Powershell is easily as good as anything DEC had in 1974 and as
such is a huge advance for the desktop.
Just so that everyone know the history:
command.com - 1980
cmd.exe - 1987 (backwards compatible with command.com, but
significantly extended functionality, often via obscure syntax though)
Thanks.
Until reading your post I didn't realize that cmd.exe existed before Nt
3.1 (1993).
Personally I often feel that cmd.exe is an improvement on it's
successor.
Windows Script Host / VBScript - 1995 (not interactive, scripts only,
but very powerful via WMI)
PowerShell - 2006
Not super new.
BTW, I tried to figure out what "command line architecture" Lawrence is talking about, but didn't quite succeed.
As far as Win32 CreateProcess() function is concerned, command line
is just a string. If caller omits applicationName parameter then
system does small amount of parsing to find application name in command
line. But when caller provides applicationName parameter, which is a
most logical thing to do in any non-interactive/non-shell scenario,
then OS does not care at all about content of command line. In both
cases OS does not modify command line and passes it to child
process as is.
So, the only difference between *nix and Windows is array of
ASCIIZ strings (today, of UTF8 strings) vs single, possibly very long, null-terminated ASCII or UTF16 string.
On 5/23/2024 12:02 PM, Michael S wrote:
On Thu, 23 May 2024 09:28:16 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/23/2024 6:19 AM, Scott Dorsey wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
And just to add to the fun, CP/M, MS-DOS and then Windows NT all
copied the basic DEC-style command line architecture, while
neglecting the crucial part of a built-in command parser to handle
more sophisticated syntax. So Microsoft’s recent rediscovery that
“the command line is cool” remains hampered by this brain-dead
underlying architecture.
To give them credit, Microsoft finally realized that command.com was
hopeless and started from first principles with Powershell.
Powershell is easily as good as anything DEC had in 1974 and as
such is a huge advance for the desktop.
Just so that everyone know the history:
command.com - 1980
cmd.exe - 1987 (backwards compatible with command.com, but
significantly extended functionality, often via obscure syntax though)
Thanks.
Until reading your post I didn't realize that cmd.exe existed before Nt
3.1 (1993).
Personally I often feel that cmd.exe is an improvement on it's
successor.
Windows Script Host / VBScript - 1995 (not interactive, scripts only,
but very powerful via WMI)
PowerShell - 2006
Not super new.
BTW, I tried to figure out what "command line architecture" Lawrence is
talking about, but didn't quite succeed.
Neither did I.
As far as Win32 CreateProcess() function is concerned, command line
is just a string. If caller omits applicationName parameter then
system does small amount of parsing to find application name in command
line. But when caller provides applicationName parameter, which is a
most logical thing to do in any non-interactive/non-shell scenario,
then OS does not care at all about content of command line. In both
cases OS does not modify command line and passes it to child
process as is.
The concept is pretty common.
VMS LIB$SPAWN and C system also use full command line.
So, the only difference between *nix and Windows is array of
ASCIIZ strings (today, of UTF8 strings) vs single, possibly very long,
null-terminated ASCII or UTF16 string.
In most practical usages it does not matter at all.
But it can matter if one needs to construct a single command
line from multiple arguments and those arguments contain
spaces or shell operators.
Example:
https://nvd.nist.gov/vuln/detail/CVE-2024-24576
Arne
VMS really wants you to use a DCL-style syntax for your command lines. It does weird things like uppercasing text in the command buffer, except for parts in quotes, which are left as-is, but then the quotes are also left
in place, so command-line parsers have to worry about dealing with text
that might or might not be quoted.
And also implicit in all this is that the command will be executed by
sending a request to some CLI/shell.
On 5/23/24 17:41, Arne Vajhøj wrote:
On 5/23/2024 12:02 PM, Michael S wrote:
On Thu, 23 May 2024 09:28:16 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/23/2024 6:19 AM, Scott Dorsey wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
And just to add to the fun, CP/M, MS-DOS and then Windows NT all
copied the basic DEC-style command line architecture, while
neglecting the crucial part of a built-in command parser to
handle more sophisticated syntax. So Microsoft’s recent
rediscovery that “the command line is cool” remains hampered by >>>>> this brain-dead underlying architecture.
To give them credit, Microsoft finally realized that command.com
was hopeless and started from first principles with Powershell.
Powershell is easily as good as anything DEC had in 1974 and as
such is a huge advance for the desktop.
Just so that everyone know the history:
command.com - 1980
cmd.exe - 1987 (backwards compatible with command.com, but
significantly extended functionality, often via obscure syntax
though)
Thanks.
Until reading your post I didn't realize that cmd.exe existed
before Nt 3.1 (1993).
Personally I often feel that cmd.exe is an improvement on it's
successor.
Windows Script Host / VBScript - 1995 (not interactive, scripts
only, but very powerful via WMI)
PowerShell - 2006
Not super new.
BTW, I tried to figure out what "command line architecture"
Lawrence is talking about, but didn't quite succeed.
Neither did I.
As far as Win32 CreateProcess() function is concerned, command line
is just a string. If caller omits applicationName parameter then
system does small amount of parsing to find application name in
command line. But when caller provides applicationName parameter,
which is a most logical thing to do in any
non-interactive/non-shell scenario, then OS does not care at all
about content of command line. In both cases OS does not modify
command line and passes it to child process as is.
The concept is pretty common.
VMS LIB$SPAWN and C system also use full command line.
So, the only difference between *nix and Windows is array of
ASCIIZ strings (today, of UTF8 strings) vs single, possibly very
long, null-terminated ASCII or UTF16 string.
In most practical usages it does not matter at all.
But it can matter if one needs to construct a single command
line from multiple arguments and those arguments contain
spaces or shell operators.
Example:
https://nvd.nist.gov/vuln/detail/CVE-2024-24576
Arne
Unix shell just uses single quotes to enclose spaced arguments, which
are then removed by the shell, before storing the argument as pointer
to a null terminated array of char. Neat, clean and simple.
At parser level, there has to be some agreed token(s) to delimit the
command line arguments and spaces or tabs are still the simplest way
to handle that. Things like spaces in filenames are a bit of an
abomination, but thank uSoft for that. How would you handle it ?...
Chris
Unix shell just uses single quotes to enclose spaced arguments, which
are then removed by the shell, before storing the argument as pointer to
a null terminated array of char. Neat, clean and simple.
On 5/23/2024 12:16 AM, Lawrence D'Oliveiro wrote:
VMS really wants you to use a DCL-style syntax for your command lines.
It does weird things like uppercasing text in the command buffer,
except for parts in quotes, which are left as-is, but then the quotes
are also left in place, so command-line parsers have to worry about
dealing with text that might or might not be quoted.
That is an oversimplified view on a complex issue.
As far as Win32 CreateProcess() function is concerned, command line is
just a string.
If caller omits applicationName parameter then system
does small amount of parsing to find application name in command line.
But when caller provides applicationName parameter, which is a most
logical thing to do in any non-interactive/non-shell scenario, then OS
does not care at all about content of command line.
On 5/23/2024 12:16 AM, Lawrence D'Oliveiro wrote:
VMS really wants you to use a DCL-style syntax for your command lines. It
does weird things like uppercasing text in the command buffer, except for
parts in quotes, which are left as-is, but then the quotes are also left
in place, so command-line parsers have to worry about dealing with text
that might or might not be quoted.
That is an oversimplified view on a complex issue.
real: ABC def "GIH" "jkl"
parse=traditional:
CLI : ABC DEF GIH jkl
FC : ABC DEF "GIH" "jkl"
Mix : ABC DEF GIH jkl
C : abc def GIH jkl
DCL : ABC DEF GIH jkl
parse=extended:
CLI : ABC DEF GIH jkl
FC : ABC def "GIH" "jkl"
Mix : ABC DEF GIH jkl
C : ABC def GIH jkl
DCL : ABC DEF GIH jkl
For details see below.
Arne
$ type cli.for
program cli
integer*4 p1len,p2len,p3len,p4len
character*80 p1,p2,p3,p4
call cli$get_value('p1',p1,p1len)
call cli$get_value('p2',p2,p2len)
call cli$get_value('p3',p3,p3len)
call cli$get_value('p4',p4,p4len)
write(*,*) 'CLI : '//p1(1:p1len)//' '//p2(1:p2len)//' '
+ //p3(1:p3len)//' '//p4(1:p4len)
end
$ type cli.cld
define verb cli
image "sys$disk:[]cli.exe"
parameter p1
parameter p2
parameter p3
parameter p4
$ for cli
$ link cli
$ set comm cli.cld
$ type mix.for
program mix
integer*4 cmdlen
character*80 cmd
integer*4 p1len,p2len,p3len,p4len
character*80 p1,p2,p3,p4
external mixcld
call lib$get_foreign(cmd,,cmdlen)
call cli$dcl_parse('cli '//cmd(1:cmdlen),mixcld,,,)
call cli$get_value('p1',p1,p1len)
call cli$get_value('p2',p2,p2len)
call cli$get_value('p3',p3,p3len)
call cli$get_value('p4',p4,p4len)
write(*,*) 'Mix : '//p1(1:p1len)//' '//p2(1:p2len)//' '
+ //p3(1:p3len)//' '//p4(1:p4len)
end
$ type mixcld.cld
module mixcld
define verb cli
parameter p1
parameter p2
parameter p3
parameter p4
$ for mix
$ set command/object mixcld
$ link mix + mixcld
$ type fc.for
program fc
integer*4 cmdlen
character*80 cmd
call lib$get_foreign(cmd,,cmdlen)
write(*,*) 'FC : '//cmd(1:cmdlen)
end
$ for fc
$ link fc
$ type c.c
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("C :");
for(int i = 1; i < argc; i++) printf(" %s", argv[i]);
printf("\n");
return 0;
}
$ cc c
$ link c
$ type dcl.com
$ write sys$output "DCL : ''p1' ''p2' ''p3' ''p4'"
Unix shell just uses single quotes to enclose spaced arguments, which
are then removed by the shell, before storing the argument as pointer to
a null terminated array of char. Neat, clean and simple.
The difference is that single quotes prevent further interpretation of
the arguments, and double quotes don't (so that you can have shell
variables in there, for instance)
Example:
https://nvd.nist.gov/vuln/detail/CVE-2024-24576
But yes if you want to use command line arguments then you need a
command line interface present.
On 5/23/24 2:05 PM, Arne Vajhøj wrote:
On 5/23/2024 12:16 AM, Lawrence D'Oliveiro wrote:
VMS really wants you to use a DCL-style syntax for your command
lines. It
does weird things like uppercasing text in the command buffer, except
for
parts in quotes, which are left as-is, but then the quotes are also left >>> in place, so command-line parsers have to worry about dealing with text
that might or might not be quoted.
That is an oversimplified view on a complex issue.
real: ABC def "GIH" "jkl"
parse=traditional:
CLI : ABC DEF GIH jkl
FC : ABC DEF "GIH" "jkl"
Mix : ABC DEF GIH jkl
C : abc def GIH jkl
DCL : ABC DEF GIH jkl
parse=extended:
CLI : ABC DEF GIH jkl
FC : ABC def "GIH" "jkl"
Mix : ABC DEF GIH jkl
C : ABC def GIH jkl
DCL : ABC DEF GIH jkl
Good summary. Did you have DECC$ARGV_PARSE_STYLE defined for the C
example?
On Thu, 23 May 2024 15:05:42 -0400, Arne Vajhøj wrote:
On 5/23/2024 12:16 AM, Lawrence D'Oliveiro wrote:
VMS really wants you to use a DCL-style syntax for your command lines.
It does weird things like uppercasing text in the command buffer,
except for parts in quotes, which are left as-is, but then the quotes
are also left in place, so command-line parsers have to worry about
dealing with text that might or might not be quoted.
That is an oversimplified view on a complex issue.
What you have done is rely on library routines to impose a commonality on
the underlying raw command buffer contents.
And those library routines are CLI-specific,
as I recall; notwithstanding their “cli$” name prefix, they are part of DCL itself.
Like I said, on *nix systems, there is no automatic assumption that you
need the intervention of a CLI/shell just for one program to execute
another.
On 5/23/2024 6:36 PM, Lawrence D'Oliveiro wrote:
And those library
routines are
CLI-specific,
I doubt that. I would expect any proper CLI on VMS to work with them
as I recall; notwithstanding their “cli$” name prefix, they
are part of DCL itself.
No. They are utility routines.
And they reside in STARLET.OLB module CLI$INTERFACE.
On 5/23/2024 6:32 PM, Craig A. Berry wrote:
On 5/23/24 2:05 PM, Arne Vajhøj wrote:
Arne
On 5/23/2024 6:36 PM, Lawrence D'Oliveiro wrote:
as I recall; notwithstanding their “cli$” name prefix, they
are part of DCL itself.
No. They are utility routines.
And they reside in STARLET.OLB module CLI$INTERFACE.
On *nix there is little difference between a shell and another program.
Huge difference on VMS.
On 5/23/2024 6:32 PM, Craig A. Berry wrote:
On 5/23/24 2:05 PM, Arne Vajhøj wrote:
real: ABC def "GIH" "jkl"
parse=extended:
C : ABC def GIH jkl
Good summary. Did you have DECC$ARGV_PARSE_STYLE defined for the C
example?
Looks that way:
$ sh log *pars*
(LNM$PROCESS_TABLE)
"DECC$ARGV_PARSE_STYLE" = "enable"
Note that I have not set it explicit - something
has set it for me.
A little investigation reveals that it is Java:
$ sear disk0:[sys0.syscommon.openjdk$80.com]java$setup.com decc
$ define'defopt' decc$fd_locking true
$ define'defopt' decc$efs_case_preserve enable ! Enable ODS-5 names
$ define'defopt' decc$readdir_dropdotnotype enable
$ define'defopt' decc$efs_charset enable
$ define'defopt' decc$argv_parse_style enable
Perhaps, but from a programmers point of view, the elegance of the shell command line method is that on entry to main(), both the arg count and
args are separated and ready to verify and use. All the background
legwork is done for you.
If you just hand the whole command line to a program, you have to
parse and separate the args, for every program you write, very bug
prone and added effort. Whole idea of good system design is to free
the programmer from repetition, and mundane stuff that the system
should deal with...
Moving pointers between address spaces is never very simple. Moving variable-length arrays of pointers adds another level of complexity on
top of it.
Not a rocket science, but not as simple as copying a single monolithic string.
On 5/23/24 6:22 PM, Arne Vajhøj wrote:
On 5/23/2024 6:32 PM, Craig A. Berry wrote:
On 5/23/24 2:05 PM, Arne Vajhøj wrote:
real: ABC def "GIH" "jkl"
parse=extended:
C : ABC def GIH jkl
Good summary. Did you have DECC$ARGV_PARSE_STYLE defined for the C
example?
Looks that way:
$ sh log *pars*
(LNM$PROCESS_TABLE)
"DECC$ARGV_PARSE_STYLE" = "enable"
I think if you deassign it you'll get abc not ABC.
As illustrated by the Rust issue.
On Fri, 24 May 2024 08:13:04 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
As illustrated by the Rust issue.
I was not able to figure out what exactly Rust guys were trying to
achieve. Feeding cmd.exe with command line from untrusted source and expecting no harm sounds like mission impossible.
That is, impossible when you run cmd.exe under privileged account.
It is possible when you run it under sufficiently deprived account, but
that is orthogonal to parsing of command line.
On 5/24/2024 9:32 AM, Michael S wrote:
On Fri, 24 May 2024 08:13:04 -0400
Arne Vajhj <arne@vajhoej.dk> wrote:
As illustrated by the Rust issue.
I was not able to figure out what exactly Rust guys were trying to
achieve. Feeding cmd.exe with command line from untrusted source and expecting no harm sounds like mission impossible.
That is, impossible when you run cmd.exe under privileged account.
It is possible when you run it under sufficiently deprived account,
but that is orthogonal to parsing of command line.
To my very limited understanding then the problem was that:
Command::new("program").arg("a1").arg("a2")
ended up as:
program a1 a2
not:
program "a1" "a2"
which is fine but is also meant that:
Command::new("program").arg("a1").arg("a2 x y z")
ended up as:
program a1 a2 x y z
not:
program "a1" "a2 x y z"
which is not so fine.
It is definitely a functional problem.
And if the security depends on program treating the two
arguments securely, then it is also a security problem.
Arne
On Fri, 24 May 2024 09:42:49 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/24/2024 9:32 AM, Michael S wrote:
On Fri, 24 May 2024 08:13:04 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
As illustrated by the Rust issue.
I was not able to figure out what exactly Rust guys were trying to
achieve. Feeding cmd.exe with command line from untrusted source and
expecting no harm sounds like mission impossible.
That is, impossible when you run cmd.exe under privileged account.
It is possible when you run it under sufficiently deprived account,
but that is orthogonal to parsing of command line.
To my very limited understanding then the problem was that:
Command::new("program").arg("a1").arg("a2")
ended up as:
program a1 a2
not:
program "a1" "a2"
which is fine but is also meant that:
Command::new("program").arg("a1").arg("a2 x y z")
ended up as:
program a1 a2 x y z
not:
program "a1" "a2 x y z"
which is not so fine.
It is definitely a functional problem.
And if the security depends on program treating the two
arguments securely, then it is also a security problem.
It seems like the simplest solution is to not try to run batch files by
means of spawn("cmd.exe", ...) or CreateProcess("cmd.exe", ...).
They could have use more specialized function: system() from C RTL or ShellExecuteEx() from Win32 API. The former is easier to use, the later
works as expected in wider range of host console environments, most importantly, it works from mintty.
On 5/24/2024 11:11 AM, Michael S wrote:
On Fri, 24 May 2024 09:42:49 -0400
Arne Vajhj <arne@vajhoej.dk> wrote:
On 5/24/2024 9:32 AM, Michael S wrote:
On Fri, 24 May 2024 08:13:04 -0400
Arne Vajhj <arne@vajhoej.dk> wrote:
As illustrated by the Rust issue.
I was not able to figure out what exactly Rust guys were trying to
achieve. Feeding cmd.exe with command line from untrusted source
and expecting no harm sounds like mission impossible.
That is, impossible when you run cmd.exe under privileged account.
It is possible when you run it under sufficiently deprived
account, but that is orthogonal to parsing of command line.
To my very limited understanding then the problem was that:
Command::new("program").arg("a1").arg("a2")
ended up as:
program a1 a2
not:
program "a1" "a2"
which is fine but is also meant that:
Command::new("program").arg("a1").arg("a2 x y z")
ended up as:
program a1 a2 x y z
not:
program "a1" "a2 x y z"
which is not so fine.
It is definitely a functional problem.
And if the security depends on program treating the two
arguments securely, then it is also a security problem.
It seems like the simplest solution is to not try to run batch
files by means of spawn("cmd.exe", ...) or CreateProcess("cmd.exe",
...). They could have use more specialized function: system() from
C RTL or ShellExecuteEx() from Win32 API. The former is easier to
use, the later works as expected in wider range of host console environments, most importantly, it works from mintty.
Both system and ShellExecuteEx still take all parameters as a single
string, which require some non-trivial conversion from array of
parameters to that string.
Arne
On 5/24/2024 11:11 AM, Michael S wrote:
On Fri, 24 May 2024 09:42:49 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/24/2024 9:32 AM, Michael S wrote:
On Fri, 24 May 2024 08:13:04 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
As illustrated by the Rust issue.
I was not able to figure out what exactly Rust guys were trying to
achieve. Feeding cmd.exe with command line from untrusted source and
expecting no harm sounds like mission impossible.
That is, impossible when you run cmd.exe under privileged account.
It is possible when you run it under sufficiently deprived account,
but that is orthogonal to parsing of command line.
To my very limited understanding then the problem was that:
Command::new("program").arg("a1").arg("a2")
ended up as:
program a1 a2
not:
program "a1" "a2"
which is fine but is also meant that:
Command::new("program").arg("a1").arg("a2 x y z")
ended up as:
program a1 a2 x y z
not:
program "a1" "a2 x y z"
which is not so fine.
It is definitely a functional problem.
And if the security depends on program treating the two
arguments securely, then it is also a security problem.
It seems like the simplest solution is to not try to run batch files by
means of spawn("cmd.exe", ...) or CreateProcess("cmd.exe", ...).
They could have use more specialized function: system() from C RTL or
ShellExecuteEx() from Win32 API. The former is easier to use, the later
works as expected in wider range of host console environments, most
importantly, it works from mintty.
Both system and ShellExecuteEx still take all parameters as a single
string, which require some non-trivial conversion from array of
parameters to that string.
It seems like the simplest solution is to not try to run batch files ...
I was not able to figure out what exactly Rust guys were trying to
achieve.
On Fri, 24 May 2024 11:28:05 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/24/2024 11:11 AM, Michael S wrote:
It seems like the simplest solution is to not try to run batch
files by means of spawn("cmd.exe", ...) or CreateProcess("cmd.exe",
...). They could have use more specialized function: system() from
C RTL or ShellExecuteEx() from Win32 API. The former is easier to
use, the later works as expected in wider range of host console
environments, most importantly, it works from mintty.
Both system and ShellExecuteEx still take all parameters as a single
string, which require some non-trivial conversion from array of
parameters to that string.
Conversion is actually trivial - dumb double-quoting.
There is an opposite problem - the child will get parameters together
with double quotes.
On 5/24/24 10:28 AM, Arne Vajhøj wrote:
On 5/24/2024 11:11 AM, Michael S wrote:
It seems like the simplest solution is to not try to run batch files by
means of spawn("cmd.exe", ...) or CreateProcess("cmd.exe", ...).
They could have use more specialized function: system() from C RTL or
ShellExecuteEx() from Win32 API. The former is easier to use, the later
works as expected in wider range of host console environments, most
importantly, it works from mintty.
Both system and ShellExecuteEx still take all parameters as a single
string, which require some non-trivial conversion from array of
parameters to that string.
The Windows CRT has _spawn() [1] which looks pretty similar to
posix_spawn() [2]. With either one you pass arguments or an array of arguments rather than a complete command line. From the docs it sounds
like on Windows the arguments get concatenated under the hood, but at
least "someone else" is doing that rather than each program having to
take responsibility for it.
[1]
There was a mention sometime in the last couple of years that
posix_spawn() is being added to the VMS CRTL.
[2] https://pubs.opengroup.org/onlinepubs/9699919799.2013edition/functions/posix_spawn.html
On Fri, 24 May 2024 19:05:40 +0300, Michael S wrote:
Conversion is actually trivial - dumb double-quoting.
What do you do if the value has quotes?
Conversion is actually trivial - dumb double-quoting.
On 5/24/2024 8:20 PM, Lawrence D'Oliveiro wrote:
On Fri, 24 May 2024 19:05:40 +0300, Michael S wrote:
Conversion is actually trivial - dumb double-quoting.
What do you do if the value has quotes?
1 double-quote -> 2 double-quotes
On Fri, 24 May 2024 20:27:38 -0400, Arne Vajhøj wrote:
On 5/24/2024 8:20 PM, Lawrence D'Oliveiro wrote:
On Fri, 24 May 2024 19:05:40 +0300, Michael S wrote:
Conversion is actually trivial - dumb double-quoting.
What do you do if the value has quotes?
1 double-quote -> 2 double-quotes
Assuming the receiving end implements the same convention. Otherwise you
have trouble.
On 5/24/2024 8:42 PM, Lawrence D'Oliveiro wrote:
On Fri, 24 May 2024 20:27:38 -0400, Arne Vajhøj wrote:
On 5/24/2024 8:20 PM, Lawrence D'Oliveiro wrote:
On Fri, 24 May 2024 19:05:40 +0300, Michael S wrote:
Conversion is actually trivial - dumb double-quoting.
What do you do if the value has quotes?
1 double-quote -> 2 double-quotes
Assuming the receiving end implements the same convention. Otherwise you
have trouble.
????
The receiving end does not see any of the added double quotes.
Windows use ' -> "" and Linux (bash) use " -> \".
On 5/24/2024 8:42 PM, Lawrence D'Oliveiro wrote:
On Fri, 24 May 2024 20:27:38 -0400, Arne Vajhøj wrote:
On 5/24/2024 8:20 PM, Lawrence D'Oliveiro wrote:
On Fri, 24 May 2024 19:05:40 +0300, Michael S wrote:
Conversion is actually trivial - dumb double-quoting.
What do you do if the value has quotes?
1 double-quote -> 2 double-quotes
Assuming the receiving end implements the same convention. Otherwise
you have trouble.
????
The receiving end does not see any of the added double quotes.
On 5/24/2024 12:05 PM, Michael S wrote:
On Fri, 24 May 2024 11:28:05 -0400
Arne Vajhj <arne@vajhoej.dk> wrote:
On 5/24/2024 11:11 AM, Michael S wrote:
It seems like the simplest solution is to not try to run batch
files by means of spawn("cmd.exe", ...) or
CreateProcess("cmd.exe", ...). They could have use more
specialized function: system() from C RTL or ShellExecuteEx()
from Win32 API. The former is easier to use, the later works as
expected in wider range of host console environments, most
importantly, it works from mintty.
Both system and ShellExecuteEx still take all parameters as a
single string, which require some non-trivial conversion from
array of parameters to that string.
Conversion is actually trivial - dumb double-quoting.
Maybe.
There is an opposite problem - the child will get parameters
together with double quotes.
They should be stripped by the shell.
Arne
On Thu, 23 May 2024 18:37:35 +0100
chrisq <devzero@nospam.com> wrote:
On 5/23/24 17:41, Arne Vajhøj wrote:
On 5/23/2024 12:02 PM, Michael S wrote:
On Thu, 23 May 2024 09:28:16 -0400
Arne Vajhøj <arne@vajhoej.dk> wrote:
On 5/23/2024 6:19 AM, Scott Dorsey wrote:
Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
And just to add to the fun, CP/M, MS-DOS and then Windows NT all
copied the basic DEC-style command line architecture, while
neglecting the crucial part of a built-in command parser to
handle more sophisticated syntax. So Microsoft’s recent
rediscovery that “the command line is cool” remains hampered by
this brain-dead underlying architecture.
To give them credit, Microsoft finally realized that command.com
was hopeless and started from first principles with Powershell.
Powershell is easily as good as anything DEC had in 1974 and as
such is a huge advance for the desktop.
Just so that everyone know the history:
command.com - 1980
cmd.exe - 1987 (backwards compatible with command.com, but
significantly extended functionality, often via obscure syntax
though)
Thanks.
Until reading your post I didn't realize that cmd.exe existed
before Nt 3.1 (1993).
Personally I often feel that cmd.exe is an improvement on it's
successor.
Windows Script Host / VBScript - 1995 (not interactive, scripts
only, but very powerful via WMI)
PowerShell - 2006
Not super new.
BTW, I tried to figure out what "command line architecture"
Lawrence is talking about, but didn't quite succeed.
Neither did I.
As far as Win32 CreateProcess() function is concerned, command line
is just a string. If caller omits applicationName parameter then
system does small amount of parsing to find application name in
command line. But when caller provides applicationName parameter,
which is a most logical thing to do in any
non-interactive/non-shell scenario, then OS does not care at all
about content of command line. In both cases OS does not modify
command line and passes it to child process as is.
The concept is pretty common.
VMS LIB$SPAWN and C system also use full command line.
So, the only difference between *nix and Windows is array of
ASCIIZ strings (today, of UTF8 strings) vs single, possibly very
long, null-terminated ASCII or UTF16 string.
In most practical usages it does not matter at all.
But it can matter if one needs to construct a single command
line from multiple arguments and those arguments contain
spaces or shell operators.
Example:
https://nvd.nist.gov/vuln/detail/CVE-2024-24576
Unix shell just uses single quotes to enclose spaced arguments, which
are then removed by the shell, before storing the argument as pointer
to a null terminated array of char. Neat, clean and simple.
Moving pointers between address spaces is never very simple. Moving >variable-length arrays of pointers adds another level of complexity on
top of it.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 432 |
Nodes: | 16 (2 / 14) |
Uptime: | 21:17:44 |
Calls: | 9,080 |
Calls today: | 3 |
Files: | 13,407 |
Messages: | 6,021,321 |