[Info-vax] Command Line Versus Command Line

Arne Vajhøj arne at vajhoej.dk
Fri May 24 20:12:39 EDT 2024


On 5/24/2024 12:45 PM, Craig A. Berry wrote:
> 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]
 > 
https://learn.microsoft.com/en-us/cpp/c-runtime-library/spawn-wspawn-functions?view=msvc-170

That looked very promising.

But a test did keep the optimism.

parmdump.c:

#include <stdio.h>

int main(int argc, char *argv[])
{
     for(int i = 0; i < argc; i++)
     {
         printf("%d : %s\n", i, argv[i]);
     }
     return 0;
}

demo.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>

void bad(const char *a1, const char *a2)
{
     printf("Bad\n");
     char cmd[1000];
     snprintf(cmd, sizeof(cmd), "parmdump %s %s", a1, a2);
     system(cmd);
}

void mystrcat(char *to, const char *from)
{
     int ix = strlen(to);
     for(int i = 0; i <= strlen(from); i++)
     {
         if(from[i] == '"')
         {
             to[ix] = from[i];
             ix++;
             to[ix] = from[i];
             ix++;
         }
         else
         {
             to[ix] = from[i];
             ix++;
         }
     }
}

void hack(const char *a1, const char *a2)
{
     char *pto, *pfrom;
     printf("Hack\n");
     char cmd[1000];
     strcpy(cmd, "parmdump \"");
     mystrcat(cmd, a1);
     strcat(cmd, "\" \"");
     mystrcat(cmd, a2);
     strcat(cmd, "\"");
     system(cmd);
}

void latest_l(const char *a1, const char *a2)
{
     printf("Latest (l)\n");
     _spawnl(_P_WAIT, "parmdump", a1, a2, NULL);
}

void latest_v(const char *a1, const char *a2)
{
     const char *argv[] = { a1, a2, NULL };
     printf("Latest (v)\n");
     _spawnv(_P_WAIT, "parmdump", argv);
}

void test(const char *a1, const char *a2)
{
     bad(a1, a2);
     hack(a1, a2);
     latest_l(a1, a2);
     latest_v(a1, a2);
}

int main()
{
     test("a", "b");
     test("a", "b c d");
     test("a", "b\"c");
     return 0;
}

Output:

Bad
0 : parmdump
1 : a
2 : b
Hack
0 : parmdump
1 : a
2 : b
Latest (l)
0 : a
1 : b
Latest (v)
0 : a
1 : b
Bad
0 : parmdump
1 : a
2 : b
3 : c
4 : d
Hack
0 : parmdump
1 : a
2 : b c d
Latest (l)
0 : a
1 : b
2 : c
3 : d
Latest (v)
0 : a
1 : b
2 : c
3 : d
Bad
0 : parmdump
1 : a
2 : bc
Hack
0 : parmdump
1 : a
2 : b"c
Latest (l)
0 : a
1 : bc
Latest (v)
0 : a
1 : bc

Unless I am doing something wrong then these _spawn functions still
expect the caller to handle the proper quoting to avoid problems.

> 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

I don't see it in 9.2-2.

Arne





More information about the Info-vax mailing list