Corinna Vinschen
2003-Sep-10 18:59 UTC
[PATCH] No extern declarations of optarg & co if getopt.h is available
Hi, I have a problem with the extern declarations of optarg, optind, etc. We're currently moving getopt from being a statically linked function to a dynamically linked function as part of the Cygwin DLL. On Windows, this requires to generate special symbols (__imp__optarg, etc.), which is done by marking the exported variables in the corresponding header. Instead of extern char *optarg; getopt.h now contains extern char __declspec(dllimport) *optarg; I'm sorry, but that's not my invention. Now the problem. ssh.c, sshd.c and a lot of other files do explicitely declare the opt* variables at the beginning of main(), even when a getopt.h file is available. The problem with this is, that this explicit extern declaration overrides the declaration from getopt.h. So instead of linking against the correct __imp__optarg symbol, the linker tries to linked against the normal _optarg. This could be easily circumvented by either not declaring the variables at all in these main() funcs, or by surrounding the declarations with #ifndef HAVE_GETOPT_H extern char *optarg; ... #endif The patch is attached. Thanks, Corinna Index: scp.c ==================================================================RCS file: /cvs/openssh_cvs/scp.c,v retrieving revision 1.118 diff -p -u -r1.118 scp.c --- scp.c 21 Aug 2003 23:34:41 -0000 1.118 +++ scp.c 10 Sep 2003 18:59:00 -0000 @@ -219,8 +219,10 @@ main(int argc, char **argv) int ch, fflag, tflag, status; double speed; char *targ, *endp; +#ifndef HAVE_GETOPT_H extern char *optarg; extern int optind; +#endif __progname = ssh_get_progname(argv[0]); Index: sftp.c ==================================================================RCS file: /cvs/openssh_cvs/sftp.c,v retrieving revision 1.38 diff -p -u -r1.38 sftp.c --- sftp.c 21 Aug 2003 23:34:41 -0000 1.38 +++ sftp.c 10 Sep 2003 18:59:00 -0000 @@ -129,8 +129,10 @@ main(int argc, char **argv) char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; LogLevel ll = SYSLOG_LEVEL_INFO; arglist args; +#ifndef HAVE_GETOPT_H extern int optind; extern char *optarg; +#endif __progname = ssh_get_progname(argv[0]); args.list = NULL; Index: ssh-add.c ==================================================================RCS file: /cvs/openssh_cvs/ssh-add.c,v retrieving revision 1.74 diff -p -u -r1.74 ssh-add.c --- ssh-add.c 21 Aug 2003 23:34:41 -0000 1.74 +++ ssh-add.c 10 Sep 2003 18:59:00 -0000 @@ -313,8 +313,10 @@ usage(void) int main(int argc, char **argv) { +#ifndef HAVE_GETOPT_H extern char *optarg; extern int optind; +#endif AuthenticationConnection *ac = NULL; char *sc_reader_id = NULL; int i, ch, deleting = 0, ret = 0; Index: ssh-agent.c ==================================================================RCS file: /cvs/openssh_cvs/ssh-agent.c,v retrieving revision 1.122 diff -p -u -r1.122 ssh-agent.c --- ssh-agent.c 21 Aug 2003 23:34:41 -0000 1.122 +++ ssh-agent.c 10 Sep 2003 18:59:01 -0000 @@ -1013,8 +1013,10 @@ main(int ac, char **av) #ifdef HAVE_CYGWIN int prev_mask; #endif +#ifndef HAVE_GETOPT_H extern int optind; extern char *optarg; +#endif pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; Index: ssh-keygen.c ==================================================================RCS file: /cvs/openssh_cvs/ssh-keygen.c,v retrieving revision 1.111 diff -p -u -r1.111 ssh-keygen.c --- ssh-keygen.c 8 Sep 2003 23:11:33 -0000 1.111 +++ ssh-keygen.c 10 Sep 2003 18:59:01 -0000 @@ -806,8 +806,10 @@ main(int ac, char **av) BIGNUM *start = NULL; FILE *f; +#ifndef HAVE_GETOPT_H extern int optind; extern char *optarg; +#endif __progname = ssh_get_progname(av[0]); Index: ssh-keyscan.c ==================================================================RCS file: /cvs/openssh_cvs/ssh-keyscan.c,v retrieving revision 1.56 diff -p -u -r1.56 ssh-keyscan.c --- ssh-keyscan.c 21 Aug 2003 23:34:41 -0000 1.56 +++ ssh-keyscan.c 10 Sep 2003 18:59:01 -0000 @@ -694,8 +694,10 @@ main(int argc, char **argv) int opt, fopt_count = 0; char *tname; +#ifndef HAVE_GETOPT_H extern int optind; extern char *optarg; +#endif __progname = ssh_get_progname(argv[0]); init_rng(); Index: ssh-rand-helper.c ==================================================================RCS file: /cvs/openssh_cvs/ssh-rand-helper.c,v retrieving revision 1.13 diff -p -u -r1.13 ssh-rand-helper.c --- ssh-rand-helper.c 21 Aug 2003 23:34:41 -0000 1.13 +++ ssh-rand-helper.c 10 Sep 2003 18:59:01 -0000 @@ -766,7 +766,9 @@ main(int argc, char **argv) { unsigned char *buf; int ret, ch, debug_level, output_hex, bytes; +#ifndef HAVE_GETOPT_H extern char *optarg; +#endif LogLevel ll; __progname = ssh_get_progname(argv[0]); Index: ssh.c ==================================================================RCS file: /cvs/openssh_cvs/ssh.c,v retrieving revision 1.181 diff -p -u -r1.181 ssh.c --- ssh.c 2 Sep 2003 12:58:22 -0000 1.181 +++ ssh.c 10 Sep 2003 18:59:02 -0000 @@ -208,8 +208,10 @@ main(int ac, char **av) struct stat st; struct passwd *pw; int dummy; +#ifndef HAVE_GETOPT_H extern int optind, optreset; extern char *optarg; +#endif __progname = ssh_get_progname(av[0]); init_rng(); Index: sshd.c ==================================================================RCS file: /cvs/openssh_cvs/sshd.c,v retrieving revision 1.260 diff -p -u -r1.260 sshd.c --- sshd.c 2 Sep 2003 12:51:17 -0000 1.260 +++ sshd.c 10 Sep 2003 18:59:02 -0000 @@ -797,8 +797,10 @@ usage(void) int main(int ac, char **av) { +#ifndef HAVE_GETOPT_H extern char *optarg; extern int optind; +#endif int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; pid_t pid; socklen_t fromlen; -- Corinna Vinschen Cygwin Developer Red Hat, Inc.
Ben Lindstrom
2003-Sep-10 20:32 UTC
[PATCH] No extern declarations of optarg & co if getopt.h is available
On Wed, 10 Sep 2003, Corinna Vinschen wrote:> Hi, > > I have a problem with the extern declarations of optarg, optind, etc. > > We're currently moving getopt from being a statically linked function > to a dynamically linked function as part of the Cygwin DLL. On Windows, > this requires to generate special symbols (__imp__optarg, etc.), which > is done by marking the exported variables in the corresponding header. > Instead of > > extern char *optarg; > > getopt.h now contains > > extern char __declspec(dllimport) *optarg; > > I'm sorry, but that's not my invention. > > Now the problem. ssh.c, sshd.c and a lot of other files do explicitely > declare the opt* variables at the beginning of main(), even when a > getopt.h file is available. The problem with this is, that this > explicit extern declaration overrides the declaration from getopt.h. > So instead of linking against the correct __imp__optarg symbol, the > linker tries to linked against the normal _optarg. > > This could be easily circumvented by either not declaring the variables > at all in these main() funcs, or by surrounding the declarations with > > #ifndef HAVE_GETOPT_H > extern char *optarg; > ... > #endifNo, I don't think that is right, and in fact it will break older platforms. I think your linker/compiler is doing it wrong. My understand of the C defintions of 'extern' is it requires that the variable pre-exist (either fleshed out in headers or in an assocated *.c file or library). 'extern' should never define it's own variable space. - Ben
Damien Miller
2003-Sep-11 02:27 UTC
[PATCH] No extern declarations of optarg & co if getopt.h is available
Corinna Vinschen wrote:> This could be easily circumvented by either not declaring the variables > at all in these main() funcs, or by surrounding the declarations with > > #ifndef HAVE_GETOPT_H > extern char *optarg; > ... > #endifWe would also need to test whether GETOPT_H declared the variables we want. E.g. an AC_TRY_COMPILE test in configure, then #ifndef GETOPT_H_DECL ... -d
Darren Tucker
2003-Sep-11 04:44 UTC
[PATCH] No extern declarations of optarg & co if getopt.h isavailable
Damien Miller wrote:> Corinna Vinschen wrote: > > This could be easily circumvented by either not declaring the variables > > at all in these main() funcs, or by surrounding the declarations with > > > > #ifndef HAVE_GETOPT_H > > extern char *optarg; > > ... > > #endif > > We would also need to test whether GETOPT_H declared the variables we > want. E.g. an AC_TRY_COMPILE test in configure, thenHow about the attached patch? It banishes the extern declarations to the system headers (if appropriate) or defines.h. It even compiles (on Redhat 8). Those declarations can probably be deleted from OpenBSD too, when convenient. -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. -------------- next part -------------- Index: configure.ac ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/configure.ac,v retrieving revision 1.149 diff -u -p -r1.149 configure.ac --- configure.ac 10 Sep 2003 05:22:45 -0000 1.149 +++ configure.ac 11 Sep 2003 04:08:16 -0000 @@ -689,6 +689,9 @@ AC_CHECK_DECL(tcsendbreak, [#include <termios.h>] ) +AC_CHECK_DECLS(optarg, , ,[#include <getopt.h>]) +AC_CHECK_DECLS(optind, , ,[#include <getopt.h>]) + dnl IRIX and Solaris 2.5.1 have dirname() in libgen AC_CHECK_FUNCS(dirname, [AC_CHECK_HEADERS(libgen.h)] ,[ AC_CHECK_LIB(gen, dirname,[ Index: defines.h ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/defines.h,v retrieving revision 1.102 diff -u -p -r1.102 defines.h --- defines.h 26 Aug 2003 01:58:16 -0000 1.102 +++ defines.h 11 Sep 2003 04:05:41 -0000 @@ -596,6 +596,13 @@ struct winsize { # define USE_LASTLOG #endif +#ifndef HAVE_DECL_OPTARG +extern char *optarg; +#endif +#ifndef HAVE_DECL_OPTIND +extern int optind; +#endif + /** end of login recorder definitions */ #endif /* _DEFINES_H */ Index: scp.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/scp.c,v retrieving revision 1.118 diff -u -p -r1.118 scp.c --- scp.c 21 Aug 2003 23:34:41 -0000 1.118 +++ scp.c 11 Sep 2003 04:02:35 -0000 @@ -219,8 +219,6 @@ main(int argc, char **argv) int ch, fflag, tflag, status; double speed; char *targ, *endp; - extern char *optarg; - extern int optind; __progname = ssh_get_progname(argv[0]); Index: sftp.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/sftp.c,v retrieving revision 1.38 diff -u -p -r1.38 sftp.c --- sftp.c 21 Aug 2003 23:34:41 -0000 1.38 +++ sftp.c 11 Sep 2003 04:02:35 -0000 @@ -129,8 +129,6 @@ main(int argc, char **argv) char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; LogLevel ll = SYSLOG_LEVEL_INFO; arglist args; - extern int optind; - extern char *optarg; __progname = ssh_get_progname(argv[0]); args.list = NULL; Index: ssh-add.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/ssh-add.c,v retrieving revision 1.74 diff -u -p -r1.74 ssh-add.c --- ssh-add.c 21 Aug 2003 23:34:41 -0000 1.74 +++ ssh-add.c 11 Sep 2003 04:02:35 -0000 @@ -313,8 +313,6 @@ usage(void) int main(int argc, char **argv) { - extern char *optarg; - extern int optind; AuthenticationConnection *ac = NULL; char *sc_reader_id = NULL; int i, ch, deleting = 0, ret = 0; Index: ssh-agent.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/ssh-agent.c,v retrieving revision 1.122 diff -u -p -r1.122 ssh-agent.c --- ssh-agent.c 21 Aug 2003 23:34:41 -0000 1.122 +++ ssh-agent.c 11 Sep 2003 04:03:03 -0000 @@ -1013,8 +1013,6 @@ main(int ac, char **av) #ifdef HAVE_CYGWIN int prev_mask; #endif - extern int optind; - extern char *optarg; pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; Index: ssh-keygen.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/ssh-keygen.c,v retrieving revision 1.111 diff -u -p -r1.111 ssh-keygen.c --- ssh-keygen.c 8 Sep 2003 23:11:33 -0000 1.111 +++ ssh-keygen.c 11 Sep 2003 04:03:15 -0000 @@ -806,9 +806,6 @@ main(int ac, char **av) BIGNUM *start = NULL; FILE *f; - extern int optind; - extern char *optarg; - __progname = ssh_get_progname(av[0]); SSLeay_add_all_algorithms(); Index: ssh-keyscan.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/ssh-keyscan.c,v retrieving revision 1.56 diff -u -p -r1.56 ssh-keyscan.c --- ssh-keyscan.c 21 Aug 2003 23:34:41 -0000 1.56 +++ ssh-keyscan.c 11 Sep 2003 04:03:29 -0000 @@ -694,9 +694,6 @@ main(int argc, char **argv) int opt, fopt_count = 0; char *tname; - extern int optind; - extern char *optarg; - __progname = ssh_get_progname(argv[0]); init_rng(); seed_rng(); Index: ssh-rand-helper.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/ssh-rand-helper.c,v retrieving revision 1.13 diff -u -p -r1.13 ssh-rand-helper.c --- ssh-rand-helper.c 21 Aug 2003 23:34:41 -0000 1.13 +++ ssh-rand-helper.c 11 Sep 2003 04:03:56 -0000 @@ -766,7 +766,6 @@ main(int argc, char **argv) { unsigned char *buf; int ret, ch, debug_level, output_hex, bytes; - extern char *optarg; LogLevel ll; __progname = ssh_get_progname(argv[0]); Index: ssh.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/ssh.c,v retrieving revision 1.181 diff -u -p -r1.181 ssh.c --- ssh.c 2 Sep 2003 12:58:22 -0000 1.181 +++ ssh.c 11 Sep 2003 04:02:44 -0000 @@ -208,8 +208,6 @@ main(int ac, char **av) struct stat st; struct passwd *pw; int dummy; - extern int optind, optreset; - extern char *optarg; __progname = ssh_get_progname(av[0]); init_rng(); Index: sshd.c ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/sshd.c,v retrieving revision 1.260 diff -u -p -r1.260 sshd.c --- sshd.c 2 Sep 2003 12:51:17 -0000 1.260 +++ sshd.c 11 Sep 2003 04:02:44 -0000 @@ -797,8 +797,6 @@ usage(void) int main(int ac, char **av) { - extern char *optarg; - extern int optind; int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; pid_t pid; socklen_t fromlen; Index: openbsd-compat/openbsd-compat.h ==================================================================RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/openbsd-compat/openbsd-compat.h,v retrieving revision 1.24 diff -u -p -r1.24 openbsd-compat.h --- openbsd-compat/openbsd-compat.h 29 Aug 2003 16:59:52 -0000 1.24 +++ openbsd-compat/openbsd-compat.h 11 Sep 2003 04:31:10 -0000 @@ -120,6 +120,9 @@ int getgrouplist(const char *, gid_t, gi #if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET) int BSDgetopt(int argc, char * const *argv, const char *opts); +extern char *BSDoptarg; +extern int BSDoptind; +extern int BSDoptreset; #endif