why was the VAR 'optind' never changed in initdb?

Started by Clover Whitealmost 14 years ago8 messages
#1Clover White
mywhiteclover@gmail.com

Hi,
I'm debugging initdb using gdb.
I found that I could not step in the function getopt_long in line 2572 in
initdb.c.
I also found that the value of VAR optind never be changed. VAR optind is
always equal to 1 but how could optind be larger than the value of argc(the
value of argc is 6) in line 2648 and 2654.

I was so confused. Could someone give me some help? Thank you~

here is my configure:
./configure CFLAGS=-O0 --enable-debug --enable-depend --enable-cassert
--prefix=/home/pgsql/pgsql

follows is my debug log by gdb:

[pgsql@vmlinux postgresql-9.1.2]$ gdb initdb
GNU gdb Red Hat Linux (6.3.0.0-1.63rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host
libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) set args -U pgsql -W -D /home/pgsql/pg_data
(gdb) b main
Breakpoint 1 at 0x804d133: file initdb.c, line 2553.
(gdb) b 2572
Breakpoint 2 at 0x804d20c: file initdb.c, line 2572.
(gdb) run
Starting program: /home/pgsql/pgsql/bin/initdb -U pgsql -W -D
/home/pgsql/pg_data

Breakpoint 1, main (argc=6, argv=0xbfec0ad4) at initdb.c:2553
2553 progname = get_progname(argv[0]);
(gdb) c
Continuing.

Breakpoint 2, main (argc=6, argv=0xbfec0ad4) at initdb.c:2572
2572 while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:sT:X:",
long_options, &option_index)) != -1)
(gdb) p optind
$1 = 1
(gdb) s
2574 switch (c)
(gdb) n
2589 username = xstrdup(optarg);
(gdb)
2590 break;
(gdb) p optind
$2 = 1
(gdb) n

Breakpoint 2, main (argc=6, argv=0xbfec0ad4) at initdb.c:2572
2572 while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:sT:X:",
long_options, &option_index)) != -1)
(gdb) p optind
$3 = 1
(gdb) n
2574 switch (c)
(gdb) p optind
$4 = 1
(gdb) n
2586 pwprompt = true;
(gdb)
2587 break;
(gdb)

Breakpoint 2, main (argc=6, argv=0xbfec0ad4) at initdb.c:2572
2572 while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:sT:X:",
long_options, &option_index)) != -1)
(gdb) p optind
$5 = 1
(gdb) n
2574 switch (c)
(gdb)
2580 pg_data = xstrdup(optarg);
(gdb) p optarg
$6 = 0x0
(gdb) n
2581 break;
(gdb) p optarg
$7 = 0x0
(gdb) n

Breakpoint 2, main (argc=6, argv=0xbfec0ad4) at initdb.c:2572
2572 while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:sT:X:",
long_options, &option_index)) != -1)
(gdb) p pg_data
$8 = 0x9d328e8 "/home/pgsql/pg_data"
(gdb) n
2648 if (optind < argc)
(gdb) p optind
$9 = 1
(gdb) p argc
$10 = 6
(gdb) n
2654 if (optind < argc)
(gdb) p optind
$11 = 1
(gdb) p argc
$12 = 6
(gdb) n
2663 if (pwprompt && pwfilename)
(gdb)

--
Clover White

#2Andrew Dunstan
andrew@dunslane.net
In reply to: Clover White (#1)
Re: why was the VAR 'optind' never changed in initdb?

On 04/09/2012 07:38 AM, Clover White wrote:

Hi,
I'm debugging initdb using gdb.
I found that I could not step in the function getopt_long in line
2572 in initdb.c.
I also found that the value of VAR optind never be changed. VAR
optind is always equal to 1 but how could optind be larger than the
value of argc(the value of argc is 6) in line 2648 and 2654.

I was so confused. Could someone give me some help? Thank you~

Why do you expect it to be? Perhaps if you tell us what problem you're
actually trying to solve we can help you better.

cheers

andrew

#3Robert Haas
robertmhaas@gmail.com
In reply to: Clover White (#1)
Re: why was the VAR 'optind' never changed in initdb?

On Mon, Apr 9, 2012 at 7:38 AM, Clover White <mywhiteclover@gmail.com> wrote:

Hi,
  I'm debugging initdb using gdb.
  I found that I could not step in the function getopt_long in line 2572 in
initdb.c.
  I also found that the value of VAR optind never be changed. VAR optind is
always equal to 1 but how could optind be larger than the value of argc(the
value of argc is 6) in line 2648 and 2654.

Read the man page for getopt_long. It changes the global variable optind.

It's a silly interface, but also a long and hallowed UNIX tradition,
so we're stuck with it.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#4Clover White
mywhiteclover@gmail.com
In reply to: Andrew Dunstan (#2)
Re: why was the VAR 'optind' never changed in initdb?

2012/4/9 Andrew Dunstan <andrew@dunslane.net>

On 04/09/2012 07:38 AM, Clover White wrote:

Hi,
I'm debugging initdb using gdb.
I found that I could not step in the function getopt_long in line 2572
in initdb.c.
I also found that the value of VAR optind never be changed. VAR optind
is always equal to 1 but how could optind be larger than the value of
argc(the value of argc is 6) in line 2648 and 2654.

I was so confused. Could someone give me some help? Thank you~

Why do you expect it to be? Perhaps if you tell us what problem you're
actually trying to solve we can help you better.

cheers

andrew

Hi, this is my story, it may be a little long :)
I mistook the parameter -W of initdb at the first time and used it like
this:
initdb -U pgsql -W 12345 -D /home/pgsql/pg_data
And I found the database was not created in the right directory, but I
could not find a log file to find out why.
So, I debug initdb and found out I have mistook the parameter -W, I
should use it like this:
initdb -U pgsql -W -D /home/pgsql/pg_data

however, when I debug initdb.c, VAR optind was supported to increased
after getopt_long pasered every parameter,
but it was alway equal to 1.

And there is a segment of initdb.c.
if (optind < argc)
{
do something statement
}

I print the value of optind and argc:

(gdb) p optind
$11 = 1
(gdb) p argc
$12 = 6

optind is obvious less than argc, but the statement above do not excute
at all.

QUESTION:
1.why does the statement above not excute?
2.why is optind always equal to 1?

--
Clover White

#5Clover White
mywhiteclover@gmail.com
In reply to: Robert Haas (#3)
Re: why was the VAR 'optind' never changed in initdb?

2012/4/9 Robert Haas <robertmhaas@gmail.com>

On Mon, Apr 9, 2012 at 7:38 AM, Clover White <mywhiteclover@gmail.com>
wrote:

Hi,
I'm debugging initdb using gdb.
I found that I could not step in the function getopt_long in line 2572

in

initdb.c.
I also found that the value of VAR optind never be changed. VAR optind

is

always equal to 1 but how could optind be larger than the value of

argc(the

value of argc is 6) in line 2648 and 2654.

Read the man page for getopt_long. It changes the global variable optind.

It's a silly interface, but also a long and hallowed UNIX tradition,
so we're stuck with it.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Thanks Robert. I have read the man page for getopt_long and optind. they
are in the same man page.

but i still could not understand why optind always equal to 1 when I gdb
initdb and print optind?
Was optind supported to increased after getopt_long pasered every
parameter?

--
Clover White

#6Andrew Dunstan
andrew@dunslane.net
In reply to: Clover White (#4)
Re: why was the VAR 'optind' never changed in initdb?

On 04/09/2012 12:36 PM, Clover White wrote:

2012/4/9 Andrew Dunstan <andrew@dunslane.net <mailto:andrew@dunslane.net>>

On 04/09/2012 07:38 AM, Clover White wrote:

Hi,
I'm debugging initdb using gdb.
I found that I could not step in the function getopt_long in
line 2572 in initdb.c.
I also found that the value of VAR optind never be changed.
VAR optind is always equal to 1 but how could optind be larger
than the value of argc(the value of argc is 6) in line 2648
and 2654.

I was so confused. Could someone give me some help? Thank you~

Why do you expect it to be? Perhaps if you tell us what problem
you're actually trying to solve we can help you better.

cheers

andrew

Hi, this is my story, it may be a little long :)
I mistook the parameter -W of initdb at the first time and used it
like this:
initdb -U pgsql -W 12345 -D /home/pgsql/pg_data
And I found the database was not created in the right directory, but
I could not find a log file to find out why.
So, I debug initdb and found out I have mistook the parameter -W, I
should use it like this:
initdb -U pgsql -W -D /home/pgsql/pg_data

This is arguably a bug. Maybe we should change this:

if (optind < argc)
{
pg_data = xstrdup(argv[optind]);
optind++;
}

to

if (optind < argc && strlen(pg_data) == 0)
{
pg_data = xstrdup(argv[optind]);
optind++;
}

i.e. we'd forbid:

initdb -D foo bar

which the OP's error more or less devolves to.

cheers

andrew

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#6)
Re: why was the VAR 'optind' never changed in initdb?

Andrew Dunstan <andrew@dunslane.net> writes:

i.e. we'd forbid:
initdb -D foo bar
which the OP's error more or less devolves to.

Makes sense. Don't we have a similar issue with psql, pg_dump, etc?

regards, tom lane

#8Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#7)
Re: why was the VAR 'optind' never changed in initdb?

On 04/09/2012 01:38 PM, Tom Lane wrote:

Andrew Dunstan<andrew@dunslane.net> writes:

i.e. we'd forbid:
initdb -D foo bar
which the OP's error more or less devolves to.

Makes sense. Don't we have a similar issue with psql, pg_dump, etc?

From a quick survey:

psql won't override a dbname or username set explicitly with an option
argument.

pg_dump doesn't have an option argument to set the dbname.

pg_restore doesn't have an option argument to set the input file name.

vacuumdb, clusterdb, reindexdb, createlang and droplang all need
remediation. createuser and dropuser look ok.

pg_ctl seems a mess :-( I'll need to look at it closer.

cheers

andrew

Show quoted text

regards, tom lane