Fix our getopt_long's behavior for a command line argument of just "-".

src/port/getopt_long.c failed on such an argument, always seeing it
as an unrecognized switch.  This is unhelpful; better is to treat such
an item as a non-switch argument.  That behavior is what we find in
GNU's getopt_long(); it's what src/port/getopt.c does; and it is
required by POSIX for getopt(), which getopt_long() ought to be
generally a superset of.  Moreover, it's expected by ecpg, which
intends an argument of "-" to mean "read from stdin".  So fix it.

Also add some documentation about ecpg's behavior in this area, since
that was miserably underdocumented.  I had to reverse-engineer it
from the code.

Per bug #16304 from James Gray.  Back-patch to all supported branches,
since this has been broken forever.

Discussion: https://postgr.es/m/16304-c662b00a1322db7f@postgresql.org
This commit is contained in:
Tom Lane 2020-03-23 11:58:00 -04:00
parent c81bd3b9a5
commit 980a70b976
2 changed files with 37 additions and 8 deletions

View File

@ -41,14 +41,21 @@ PostgreSQL documentation
<para>
<command>ecpg</command> will convert each input file given on the
command line to the corresponding C output file. Input files
preferably have the extension <filename>.pgc</filename>.
The extension will be replaced by <filename>.c</filename> to
determine the output file name.
The output file name can also be overridden using the
command line to the corresponding C output file. If an input file
name does not have any extension, <filename>.pgc</filename> is
assumed. The file's extension will be replaced
by <filename>.c</filename> to construct the output file name.
But the output file name can be overridden using the
<option>-o</option> option.
</para>
<para>
If an input file name is just <literal>-</literal>,
<command>ecpg</command> reads the program from standard input
(and writes to standard output, unless that is overridden
with <option>-o</option>).
</para>
<para>
This reference page does not describe the embedded SQL language.
See <xref linkend="ecpg"/> for more information on that topic.
@ -94,6 +101,19 @@ PostgreSQL documentation
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option></term>
<listitem>
<para>
Process header files. When this option is specified, the output file
extension becomes <literal>.h</literal> not <literal>.c</literal>,
and the default input file extension is <literal>.pgh</literal>
not <literal>.pgc</literal>. Also, the <option>-c</option> option is
forced on.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-i</option></term>
<listitem>
@ -125,6 +145,7 @@ PostgreSQL documentation
<para>
Specifies that <command>ecpg</command> should write all
its output to the given <replaceable>filename</replaceable>.
Write <literal>-o -</literal> to send all output to standard output.
</para>
</listitem>
</varlistentry>

View File

@ -79,14 +79,22 @@ getopt_long(int argc, char *const argv[],
place++;
if (place[0] && place[0] == '-' && place[1] == '\0')
{ /* found "--" */
if (!*place)
{
/* treat "-" as not being an option */
place = EMSG;
return -1;
}
if (place[0] == '-' && place[1] == '\0')
{
/* found "--", treat it as end of options */
++optind;
place = EMSG;
return -1;
}
if (place[0] && place[0] == '-' && place[1])
if (place[0] == '-' && place[1])
{
/* long option */
size_t namelen;