groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Groff] Re: MSVC Port--Behavior of spawn and exec functions


From: Jeff Conrad
Subject: [Groff] Re: MSVC Port--Behavior of spawn and exec functions
Date: Thu, 15 Jan 2004 02:22:25 -0800

There's an ugly little detail that arises in a Win32 port built with MSVC:
the handling of arguments by _spawn() differs from what might be expected.
With MSVC, arguments passed to _spawn??() or _exec??(), whether as explicit
lists or as argv vectors, are concatenated into a single string and passed
to CreateProcess() (which only accepts a single string as a commandline).
CreateProcess() then breaks the commandline string into tokens at spaces,
and passes each token to the child process as a separate argument.  Thus a
commandline

    'sh -c ls -F'

is passed to the shell as 4 separate arguments, so that the argument to the
'c' option is 'ls'.  At least with the MKS KornShell, the argument to 'c'
must be a single string, so that in the example above, the 'F' option is
ignored.  It's been a while since I've used the shell's 'c' option on a
*nix box, but as I recall, the behavior was the same--the command string
must be a single argument.

The argument splitting is obtained even if _exec is called as

    _execlp("sh", "sh", "-c", "ls -F", NULL);

If parts of the commandline string passed to CreateProcess() are enclosed
within double quotes, they are passed to the child as single arguments, so
that

    sh -c "ls -F"

works as expected.  In this case, _exec would need to be called as

    _execlp("sh", "sh", "-c", "\"ls -F\"", NULL);

The closing escaped quote apparently is unnecessary, so that

    _execlp("sh", "sh", "-c", "\"ls -F", NULL);

which is passed to CreateProcess() as

    sh -c "ls -F

also works.

The behavior of the spawn and exec functions affects groff(1) in at least
two places: filenames that contain spaces, and spooler commands that
include arguments.

    groff 'my file'

or

    groff "my file"

pass only the 'my' to troff, and fail accordingly.

    groff '"my file"'

or

    groff '"my file'

work as intended. CreateProcess() doesn't recognize single quotes, so that

    groff "'my file'"

doesn't work.

groff calls the print spooler with

    sh -c command_string

so that f the spooler is specified in DESC as

    print lp -r

the 'r' option is passed to the shell as a third argument and the spooler
never sees it.  The spooler is called properly if specified as

    print "lp -r"

but any additional spooler arguments given to groff with the 'L' option are
passed to the shell as an additional argument and are ignored.  Specifying
the spooler as

    print "lp -r

allows additional spooler arguments to be included in the command string
passed to the shell.


There would seem to be two obvious approaches to the problem:

1.  Include a Win32 note to quote any arguments that contain spaces as
    shown above, and specify the print command as shown above.  The syntax
    is ugly, if not utterly counterintuitive, and depending on the quirky
    behavior of CreateProcess() not needing the closing quote seems chancy
    at best.

2.  Include an appropriate #ifdef to have groff enclose any arguments that
    might contain spaces in double quotes.

The approach also would seem to depend on the answers to several questions:

1.  Do other shells require that commands given with the 'c' option consist
    of a single string?

2.  Do Win32 builds other than with MSVC have the same behavior of the exec
    and spawn functions?

3.  Do other Win32 builds (e.g., MinGW) of groff exhibit the specific
    problems I've mentioned?

Jeff Conrad



reply via email to

[Prev in Thread] Current Thread [Next in Thread]