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

Bug#192834: Glibc's method of resetting getopt different, causes interoperability problems



On Fri, Oct 08, 2004 at 10:55:44AM +0900, GOTO Masanori wrote:
> Hi,
> 
> > It would be nice if glibc reset its internal state if when optind is set
> > to 1, as well as when optind is set to 0.  Historically, the mechanism
> > which worked across BSD, AT&T, and most commercial unix systems derived
> > from the same require that getopt() be reset by setting optind to 1.
> > Setting optind to 0 causes getopt() to misbehave on a number of
> > platforms, most notably and most recently Mac OS X, but probably on
> > other BSD-derived systems.   
> > 
> > On the other hand, setting optind to 1 in an attempt to reset things
> > causes glibc to core dump under some conditions.
> > 
> > The lack of interoperability on this point means that I was forced to
> > work around the bug in a particularly ugly fashion, as shown below.  
> > It would be really nice if I didn't need this kind of kludgery.
> 
> Glibc defines optind = 1 in initial state in 2.3.2.ds1-17.  POSIX says
> it should be 1 before any calls.  Could you provide us more
> information or an example to reappear this report?

The problem is what happens if you want to use getopt() multiple times
to parse multiple sets of argc/argv arguments.  For example,
e2fsprogs's debugfs program uses getopt to parse each command given to
debugfs:

# debugfs /dev/hda3
debugfs: stat /
	...
debugfs: clri <2>
	...
debugfs: quit

In this case, "stat /", "clri <2>", and "quit" are all parsed using
getopt(), as well as being the command-line arguments to debugfs.

Unfortunately, gnu glibc has extra allocated memory which is used to
support long options (i.e., --help).  This information is only reset
when you set optind=0 before calling getopt() to parse a new set of
argv[] vectors.  If you do not reset optind to 0 before parsing a new
set of argv[] vectors, getopt will core dump.  Unfortunately, on BSD
systems, you have to set optind=1 before parsing a new set of argv[]
vectors, or BSD systems will core dump.

To reproduce, recompile e2fsprogs and remove the magic GLIBC branch
below, and if you always reinitialize optind=1 in reset_getopt(), you
will watch getopt core dump rather spectacularly after executing a
number of debugfs commands with and without options.

						- Ted


/*
 * This function resets the libc getopt() function, which keeps
 * internal state.  Bad design!  Stupid libc API designers!  No
 * biscuit!
 *
 * BSD-derived getopt() functions require that optind be reset to 1 in
 * order to reset getopt() state.  This used to be generally accepted
 * way of resetting getopt().  However, glibc's getopt()
 * has additional getopt() state beyond optind, and requires that
 * optind be set zero to reset its state.  So the unfortunate state of
 * affairs is that BSD-derived versions of getopt() misbehave if
 * Optind is set to 0 in order to reset getopt(), and glibc's getopt()
 * will core ump if optind is set 1 in order to reset getopt().
 * 
 * More modern versions of BSD require that optreset be set to 1 in
 * order to reset getopt().   Sigh.  Standards, anyone?
 *
 * We hide the hair here.
 */
void reset_getopt(void)
{
#ifdef __GLIBC__
	optind = 0;
#else
	optind = 1;
#endif
#ifdef HAVE_OPTRESET
	optreset = 1;		/* Makes BSD getopt happy */
#endif
}





Reply to: