This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [BUG 1.7 getopt_long() and recv()] has problem for tftp-hpa-5.0 on cygwin-1.7/win2003


Xiaoqiang Zheng wrote:
> to make the 2 BUGs more clear:
> 
> * in the while loop of processing options with '-' using
> getopt_long():
> 
> $ tftpd/tftpd -u SYSTEM -L -vvvv -p -c -s /var/log
> 
> 1. it seems the '-<x> <value>'(-u SYSTEM) argument pairs that pass
> the second argument as value have the value lost and the variable get
> null value. the '-<x>'(-L -p -c -s; -vvvv is a special one) type
> arguments that set some flag seems work well.

Here's your problem:
gcc  tftp.o main.o ../common/libcommon.a -liberty
/home/Administrator/tftp-hpa-5.0/lib/libxtra.a  -o tftp.exe

you're linking against libiberty.  You're using the getopt functions
from libiberty, which are locally bound to the optind variable inside
the -liberty library.  However, main.c probably #included getopt.h,
which on cygwin has declspec(dllimport) declarations for optind -- so,
main.o is actually linking to "__imp__optind", a redirection pointer to
the optind variable inside cygwin1.dll.

Therefore, when your main.o code tries to access optind, it "sees" the
one in cygwin1.dll, which is never incremented past one.  When you call
getopt/getopt_long, you're calling the implementation in libiberty
(which manipulates the liberty's version of the optind variable).

The solution to this problem is to either

1) don't link to libiberty, or at least, insure that -lcygwin precedes
-liberty on the link line, OR
2) do NOT include getopt.h or unistd.h, and instead force to declare all
the relevant functions and variables consistent with the versions in
-liberty (that is, without declspec(dllimport) decorations).

Try the attached getopt_decls.h file from checkx-0.2.0.  unchanged, it
implements option #1 (with a little help from the Makefile).  However,
change the #ifdef and it implements #2.

--
Chuck
/*
 * Copyright (c) 2006 Charles S. Wilson
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included 
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
 * OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef GETOPT_DECLS_H
#define GETOPT_DECLS_H


#if HAVE_CONFIG_H
# include <config.h>
#endif

/* So this is ONE way... */
#if 0

/* because we're linking against libiberty (for buildargv etc), we are
   ALSO forced to get getopt from it and NOT from cygwin.  If we 
   include getopt.h (or unistd.h), then we'd use declspec(dllimport)
   variables optind, optopt, and optarg -- but thanks to static 
   linkage, we're using libiberty's getopt() and getopt_long.

   libiberty's functions use static versions of optind, optopt, and
   optarg, NOT the declspec ones.  So, to make sure that both we 
   and libiberty are talking about the same extern variables:

   (1) do NOT #include unistd.h or getopt.h  !!!
   (2) define all the stuff from getopt.h right here.
*/
extern int opterr;
extern int optind;
extern int optopt;
extern int optreset;
extern char *optarg;
int getopt (int, char * const *, const char *);
struct option {
        const char *name;
        int  has_arg;
        int *flag;
        int val;
};
int getopt_long (int, char *const *, const char *, const struct option *, int *);
int getopt_long_only (int, char *const *, const char *, const struct option *, int *);
#define no_argument             0
#define required_argument       1
#define optional_argument       2

#else
/* The other way is to go ahead and #include getopt.h, but force linking
   to the cygwin version of getopt:
     gcc -o foo.exe  foo.o -lcygwin -liberty
   Which turns into the linker command
     .... -o foo.exe  foo.o -lcygwin -liberty -lgcc -lcygwin ...
   with 2 -lcygwin.  It looks odd, but it's okay.
*/
# if HAVE_GETOPT_H
#  include <getopt.h>
# endif
#endif

#endif


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]