PostgreSQL libraries - PThread Support, but not use...
On a slightly related note to the other threads thread [sic] going
on... Over the Christmas/New Year break i've been looking into making
the PostgreSQL client libraries (in particular libpq and ecpg)
thread-safe - that is they can safely be used by a program which
itself is using mutliple threads. I'm largely there with ecpg (globals
are protected, a sqlca for each thread), but of course it relies on
libpq which needs work to share a connection between thrreads.
Relying on thread experience from a few years back on Solaris I had
assumed I could just use the pthread_* routines in the shared
libraries and they would reference the weak symbols in libc, rather
than explicitly pull in libpthread. If the application using the
library linked to libpthreads then the 'real' thread routines would be
activated, single threaded apps wouldn't need link to
libpthread... However there seems to be no standard to which pthread_*
routines are available as weak symbols in libc (Linux and Solaris
differ).
So a couple of questions to decide the course of this work:
1. It's looking likely that the libraries will need to link to
libpthread, and as a result anything linking to the libraries will
need to link to libpthread too. Will this be accepted in a patch? A
similar problem has cropt up with the perl integration recently too
(i.e. the Perl developers have decided to link in libpthread).
2. Is their any mileage in using an abstraction layer - ACE, npr? A
Bit OTT for what i'm doing, but...
3. Am I wasting my time?
I think making the PostgreSQL libraries thread-safe/aware is very
worthwhile, but a lot of hurdles...
Thanks, Lee.
Lee Kindness <lkindness@csl.co.uk> writes:
On a slightly related note to the other threads thread [sic] going
on... Over the Christmas/New Year break i've been looking into making
the PostgreSQL client libraries (in particular libpq and ecpg)
thread-safe - that is they can safely be used by a program which
itself is using mutliple threads. I'm largely there with ecpg (globals
are protected, a sqlca for each thread), but of course it relies on
libpq which needs work to share a connection between thrreads.
AFAIK, libpq is thread-safe already, it's just not thread-aware.
What you'd presumably want is a wrapper layer that adds a mutex to
prevent multiple threads from manipulating a PGconn at the same time.
Couldn't this be done without touching libpq at all?
1. It's looking likely that the libraries will need to link to
libpthread, and as a result anything linking to the libraries will
need to link to libpthread too. Will this be accepted in a patch?
If the patch requires pthread and not any other form of thread support,
probably not. See nearby threading thread ;-)
In general I'd be unhappy with doing anything to libpq that forces
non-threaded clients to start depending on libpthread (or other thread
libraries). Thus the idea of a wrapper seems more appealing to me.
regards, tom lane
On Mon, Jan 06, 2003 at 11:58:17AM -0500, Tom Lane wrote:
AFAIK, libpq is thread-safe already, it's just not thread-aware.
What you'd presumably want is a wrapper layer that adds a mutex to
prevent multiple threads from manipulating a PGconn at the same time.
Couldn't this be done without touching libpq at all?
In fact it'd probably be better to do it without touching libpq at all,
so the application can tune for the level of thread-safety it needs.
There's no point in locking a PGresult for every time the application
wants to read a field--it'd be unacceptably slow yet some applications
may want to do it. But I'm sure this has been discussed in that other
threading thread...
Having a thread-aware wrapper multiplex a PGconn between multiple
client threads using the nonblocking functions probably isn't going to
wash either, because nonblocking operation isn't quite the same as fully
asynchronous. And even if the backend protocol allows for it, there's
no great benefit since the threads would still be waiting on the same
socket and the same backend. Better to give each thread its own PGconn
and its own file descriptor to block on, if needed.
Jeroen
Tom Lane writes:
Lee Kindness <lkindness@csl.co.uk> writes:
On a slightly related note to the other threads thread [sic] going
on... Over the Christmas/New Year break i've been looking into making
the PostgreSQL client libraries (in particular libpq and ecpg)
thread-safe - that is they can safely be used by a program which
itself is using mutliple threads. I'm largely there with ecpg (globals
are protected, a sqlca for each thread), but of course it relies on
libpq which needs work to share a connection between thrreads.AFAIK, libpq is thread-safe already, it's just not thread-aware.
What you'd presumably want is a wrapper layer that adds a mutex to
prevent multiple threads from manipulating a PGconn at the same time.
Couldn't this be done without touching libpq at all?
Certainly, it could. I've not fully investigated the current failings
of libpq WRT to threading yet. But it's certainly a bit more than I
stated above. I don't know where the statement that libpq is thread
safe originated from (I see it's on the website). but at a quick
glance I believe that krb4, krb5, PQoidStatus(),
PQsetClientEncoding(), winsock_strerror() need more though
investigation and non-thread-safe fuctions are also being used (at a
glance gethostbyname() and strtok()).
1. It's looking likely that the libraries will need to link to
libpthread, and as a result anything linking to the libraries will
need to link to libpthread too. Will this be accepted in a patch?If the patch requires pthread and not any other form of thread support,
probably not. See nearby threading thread ;-)
In general I'd be unhappy with doing anything to libpq that forces
non-threaded clients to start depending on libpthread (or other thread
libraries). Thus the idea of a wrapper seems more appealing to me.
Okay, but what about ecpg? Thread-local sqlca instances would be a
real benefit, guess Michael and Christof are the guys to talk to?
I suppose the real problem is the needed baggage with this - the
autoconf macros will be a nightmare!
Thanks, Lee.
We have definatly had requests for improved thread-safeness for libpq
and ecpg in the past, so whatever you can do would be a help. We say
libpq is thread-safe, but specifically mention the non-threadsafe calls
in the libpq documentation, or at least we should. We have been making
marginal thread-safe improvements over the years.
---------------------------------------------------------------------------
Lee Kindness wrote:
Tom Lane writes:
Lee Kindness <lkindness@csl.co.uk> writes:
On a slightly related note to the other threads thread [sic] going
on... Over the Christmas/New Year break i've been looking into making
the PostgreSQL client libraries (in particular libpq and ecpg)
thread-safe - that is they can safely be used by a program which
itself is using mutliple threads. I'm largely there with ecpg (globals
are protected, a sqlca for each thread), but of course it relies on
libpq which needs work to share a connection between thrreads.AFAIK, libpq is thread-safe already, it's just not thread-aware.
What you'd presumably want is a wrapper layer that adds a mutex to
prevent multiple threads from manipulating a PGconn at the same time.
Couldn't this be done without touching libpq at all?Certainly, it could. I've not fully investigated the current failings
of libpq WRT to threading yet. But it's certainly a bit more than I
stated above. I don't know where the statement that libpq is thread
safe originated from (I see it's on the website). but at a quick
glance I believe that krb4, krb5, PQoidStatus(),
PQsetClientEncoding(), winsock_strerror() need more though
investigation and non-thread-safe fuctions are also being used (at a
glance gethostbyname() and strtok()).1. It's looking likely that the libraries will need to link to
libpthread, and as a result anything linking to the libraries will
need to link to libpthread too. Will this be accepted in a patch?If the patch requires pthread and not any other form of thread support,
probably not. See nearby threading thread ;-)
In general I'd be unhappy with doing anything to libpq that forces
non-threaded clients to start depending on libpthread (or other thread
libraries). Thus the idea of a wrapper seems more appealing to me.Okay, but what about ecpg? Thread-local sqlca instances would be a
real benefit, guess Michael and Christof are the guys to talk to?I suppose the real problem is the needed baggage with this - the
autoconf macros will be a nightmare!Thanks, Lee.
---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian <pgman@candle.pha.pa.us> writes:
We have definatly had requests for improved thread-safeness for libpq
and ecpg in the past, so whatever you can do would be a help. We say
libpq is thread-safe, but specifically mention the non-threadsafe calls
in the libpq documentation, or at least we should.
We do:
http://www.ca.postgresql.org/users-lounge/docs/7.3/postgres/libpq-threading.html
But Lee's point about depending on possibly-unsafe libc routines is a
good one. I don't think anyone's gone through the code with an eye to
that.
regards, tom lane
On Monday 06 January 2003 12:28, Lee Kindness wrote:
Tom Lane writes:
Lee Kindness <lkindness@csl.co.uk> writes:
are protected, a sqlca for each thread), but of course it relies on
libpq which needs work to share a connection between thrreads.
AFAIK, libpq is thread-safe already, it's just not thread-aware.
Couldn't this be done without touching libpq at all?
Certainly, it could. I've not fully investigated the current failings
of libpq WRT to threading yet. But it's certainly a bit more than I
stated above. I don't know where the statement that libpq is thread
safe originated from (I see it's on the website). but at a quick
glance I believe that krb4, krb5, PQoidStatus(),
PQsetClientEncoding(), winsock_strerror() need more though
investigation and non-thread-safe fuctions are also being used (at a
glance gethostbyname() and strtok()).
Lee, see the AOLserver source code. AOLserver (www.aolserver.com) is a
multithreaded dynamic web server that supports pooled database connections.
One of the supported databases is PostgreSQL (I maintain the driver,
currently). It's dual licensed (AOLserver Public License and GPL). I've not
yet seen a problem that could be traced to libpq not being threadsafe. And
AOLserver certainly would show a non-threadsafe problem, particularly with
sites running OpenACS, which can easily beat the database to death.
BTW: thanks for the Bison RPMs. And I believe the PGDG is appropriate as
well. :-)
--
Lamar Owen
WGCR Internet Radio
1 Peter 4:11
Tom Lane writes:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
We have definatly had requests for improved thread-safeness for libpq
and ecpg in the past, so whatever you can do would be a help. We say
libpq is thread-safe, but specifically mention the non-threadsafe calls
in the libpq documentation, or at least we should.We do:
http://www.ca.postgresql.org/users-lounge/docs/7.3/postgres/libpq-threading.html
But Lee's point about depending on possibly-unsafe libc routines is a
good one. I don't think anyone's gone through the code with an eye to
that.
Right, so a reasonable angle for me to take is to go through the libpq
source looking for potential problem areas and use of "known bad"
functions. I can add autoconf checks for the replacement *_r()
functions, and use these in place of the traditional ones where
available.
If any function is found to be not thread-safe and cannot be made so
using standard library calls then it needs to be documented as such
both in the source and the aforementioned documentation.
This approach avoids any thread library dependencies and documents the
current state of play WRT thread safety (i.e it's a good, and needed,
basis for any later work).
ECPG is a separate issue, and best handled as such (it will need
thread calls). I'll post a patch for it at a later date so the changes
are available to anyone who wants to play with ECPG and threads.
Ta, Lee.
Lee Kindness wrote:
Tom Lane writes:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
We have definatly had requests for improved thread-safeness for libpq
and ecpg in the past, so whatever you can do would be a help. We say
libpq is thread-safe, but specifically mention the non-threadsafe calls
in the libpq documentation, or at least we should.We do:
http://www.ca.postgresql.org/users-lounge/docs/7.3/postgres/libpq-threading.html
But Lee's point about depending on possibly-unsafe libc routines is a
good one. I don't think anyone's gone through the code with an eye to
that.Right, so a reasonable angle for me to take is to go through the libpq
source looking for potential problem areas and use of "known bad"
functions. I can add autoconf checks for the replacement *_r()
functions, and use these in place of the traditional ones where
available.
I am a little confused by the *_r functions. Are they for all
functions? BSD/OS doesn't have them, but all our libc functions are
threadsafe except for things like strtok, where they recommend strsep,
and gethostbyname, where they would suggest getaddrinfo, I guess.
If any function is found to be not thread-safe and cannot be made so
using standard library calls then it needs to be documented as such
both in the source and the aforementioned documentation.
Ideally we will find we can get them all fixed in some way.
This approach avoids any thread library dependencies and documents the
current state of play WRT thread safety (i.e it's a good, and needed,
basis for any later work).
Yes, good idea.
ECPG is a separate issue, and best handled as such (it will need
thread calls). I'll post a patch for it at a later date so the changes
are available to anyone who wants to play with ECPG and threads.
Yes, needs to be done too. Someone was complaining about ecpg not being
thread safe several months ago. I don't remember the details.
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian writes:
Lee Kindness wrote:
Right, so a reasonable angle for me to take is to go through the libpq
source looking for potential problem areas and use of "known bad"
functions. I can add autoconf checks for the replacement *_r()
functions, and use these in place of the traditional ones where
available.I am a little confused by the *_r functions. Are they for all
functions? BSD/OS doesn't have them, but all our libc functions are
threadsafe except for things like strtok, where they recommend strsep,
and gethostbyname, where they would suggest getaddrinfo, I guess.
Some functions in the C library (and other common system libraries)
are defined in such a way to make their implementation
non-reentrant. Normally this is due to return values being supplied in
a static buffer which is overwritten by the subsequent call, or the
calls relying on static data between calls. A list such functions
would include:
asctime crypt ctime drand48 ecvt encrypt erand48 fcvt fgetgrent
fgetpwent fgetspent getaliasbyname getaliasent getdate getgrent
getgrgid getgrnam gethostbyaddr gethostbyname gethostbyname2
gethostent getlogin getnetbyaddr getnetbyname getnetent getnetgrent
getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid
getservbyname getservbyport getservent getspent getspnam getutent
getutid getutline gmtime hcreate hdestroy hsearch initstate jrand48
lcong48 localtime lrand48 mrand48 nrand48 ptsname qecvt qfcvt rand
random readdir readdir64 seed48 setkey setstate sgetspent srand48
srandom strerror strtok tmpnam ttyname
to one degree or another. The important ones to watch for are: ctime,
localtime, asctime, gmtime, readdir, strtok and tmpnam. Now these
functions are often augmented by a _r partner which fixes their API to
allow their implementations to be reentrant.
After a quick grep libpq could be using crypt, gethostbyname, random,
strerror, encrypt, getpwuid, rand and strtok. As you rightly note, ins
ome cases the correct fix is to use alternative functions and not the
_r versions - this avoids lots of ifdefs!
L.
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.
Thanks, Lee.
Lee Kindness writes:
Show quoted text
Tom Lane writes:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
We have definatly had requests for improved thread-safeness for libpq
and ecpg in the past, so whatever you can do would be a help. We say
libpq is thread-safe, but specifically mention the non-threadsafe calls
in the libpq documentation, or at least we should.We do:
http://www.ca.postgresql.org/users-lounge/docs/7.3/postgres/libpq-threading.html
But Lee's point about depending on possibly-unsafe libc routines is a
good one. I don't think anyone's gone through the code with an eye to
that.Right, so a reasonable angle for me to take is to go through the libpq
source looking for potential problem areas and use of "known bad"
functions. I can add autoconf checks for the replacement *_r()
functions, and use these in place of the traditional ones where
available.If any function is found to be not thread-safe and cannot be made so
using standard library calls then it needs to be documented as such
both in the source and the aforementioned documentation.This approach avoids any thread library dependencies and documents the
current state of play WRT thread safety (i.e it's a good, and needed,
basis for any later work).ECPG is a separate issue, and best handled as such (it will need
thread calls). I'll post a patch for it at a later date so the changes
are available to anyone who wants to play with ECPG and threads.Ta, Lee.
Attachments:
diffs-configure.txtapplication/octet-streamDownload
Index: configure
===================================================================
RCS file: /projects/cvsroot/pgsql-server/configure,v
retrieving revision 1.237
diff -c -r1.237 configure
*** configure 2003/01/07 06:37:49 1.237
--- configure 2003/01/09 13:59:13
***************
*** 10675,10680 ****
--- 10675,11333 ----
+ echo "$as_me:$LINENO: checking whether strerror_r is declared" >&5
+ echo $ECHO_N "checking whether strerror_r is declared... $ECHO_C" >&6
+ if test "${ac_cv_have_decl_strerror_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ $ac_includes_default
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ #ifndef strerror_r
+ char *p = (char *) strerror_r;
+ #endif
+
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_have_decl_strerror_r=yes
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_have_decl_strerror_r=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_have_decl_strerror_r" >&5
+ echo "${ECHO_T}$ac_cv_have_decl_strerror_r" >&6
+ if test $ac_cv_have_decl_strerror_r = yes; then
+
+ cat >>confdefs.h <<_ACEOF
+ #define HAVE_DECL_STRERROR_R 1
+ _ACEOF
+
+
+ else
+ cat >>confdefs.h <<_ACEOF
+ #define HAVE_DECL_STRERROR_R 0
+ _ACEOF
+
+
+ fi
+
+
+
+ for ac_func in strerror_r
+ do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_func" >&5
+ echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below. */
+ #include <assert.h>
+ /* Override any gcc2 internal prototype to avoid an error. */
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ /* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+ char $ac_func ();
+ char (*f) ();
+
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ /* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+ choke me
+ #else
+ f = $ac_func;
+ #endif
+
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ eval "$as_ac_var=no"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+ if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+ #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+ _ACEOF
+
+ fi
+ done
+
+ echo "$as_me:$LINENO: checking whether strerror_r returns char *" >&5
+ echo $ECHO_N "checking whether strerror_r returns char *... $ECHO_C" >&6
+ if test "${ac_cv_func_strerror_r_char_p+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+
+ ac_cv_func_strerror_r_char_p=no
+ if test $ac_cv_have_decl_strerror_r = yes; then
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ $ac_includes_default
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+
+ char buf[100];
+ char x = *strerror_r (0, buf, sizeof buf);
+ char *p = strerror_r (0, buf, sizeof buf);
+
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strerror_r_char_p=yes
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ else
+ # strerror_r is not declared. Choose between
+ # systems that have relatively inaccessible declarations for the
+ # function. BeOS and DEC UNIX 4.0 fall in this category, but the
+ # former has a strerror_r that returns char*, while the latter
+ # has a strerror_r that returns `int'.
+ # This test should segfault on the DEC system.
+ if test "$cross_compiling" = yes; then
+ :
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ $ac_includes_default
+ extern char *strerror_r ();
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ char buf[100];
+ char x = *strerror_r (0, buf, sizeof buf);
+ exit (!isalpha (x));
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_strerror_r_char_p=yes
+ else
+ echo "$as_me: program exited with status $ac_status" >&5
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+ fi
+ fi
+
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_func_strerror_r_char_p" >&5
+ echo "${ECHO_T}$ac_cv_func_strerror_r_char_p" >&6
+ if test $ac_cv_func_strerror_r_char_p = yes; then
+
+ cat >>confdefs.h <<\_ACEOF
+ #define STRERROR_R_CHAR_P 1
+ _ACEOF
+
+ fi
+
+
+
+ for ac_func in crypt_r
+ do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_func" >&5
+ echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below. */
+ #include <assert.h>
+ /* Override any gcc2 internal prototype to avoid an error. */
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ /* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+ char $ac_func ();
+ char (*f) ();
+
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ /* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+ choke me
+ #else
+ f = $ac_func;
+ #endif
+
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ eval "$as_ac_var=no"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+ if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+ #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+ _ACEOF
+
+ fi
+ done
+
+
+ if test "$ac_cv_header_pwd_h" = "yes"; then
+ echo "$as_me:$LINENO: checking for posix getpwuid_r" >&5
+ echo $ECHO_N "checking for posix getpwuid_r... $ECHO_C" >&6
+ if test "${ac_cv_func_posix_getpwuid_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5
+ echo "$as_me: error: cannot run test program while cross compiling" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+
+ #define _THREAD_SAFE
+ #define _REENTRANT
+ #define _POSIX_PTHREAD_SEMANTICS
+ #include <errno.h>
+ #include <pwd.h>
+ int main () {
+ char buffer[10000];
+ struct passwd pwd, *pwptr = &pwd;
+ int error;
+ errno = 0;
+ error = getpwuid_r (0, &pwd, buffer,
+ sizeof (buffer), &pwptr);
+ return (error < 0 && errno == ENOSYS)
+ || error == ENOSYS;
+ }
+ _ACEOF
+ rm -f conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_posix_getpwuid_r=yes
+ else
+ echo "$as_me: program exited with status $ac_status" >&5
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ( exit $ac_status )
+ ac_cv_func_posix_getpwuid_r=no
+ fi
+ rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+ fi
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_func_posix_getpwuid_r" >&5
+ echo "${ECHO_T}$ac_cv_func_posix_getpwuid_r" >&6
+ if test "$ac_cv_func_posix_getpwuid_r" = yes; then
+
+ cat >>confdefs.h <<\_ACEOF
+ #define HAVE_POSIX_GETPWUID_R 1
+ _ACEOF
+
+ else
+ echo "$as_me:$LINENO: checking for nonposix getpwuid_r" >&5
+ echo $ECHO_N "checking for nonposix getpwuid_r... $ECHO_C" >&6
+ if test "${ac_cv_func_nonposix_getpwuid_r+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ #include <pwd.h>
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ char buffer[10000];
+ struct passwd pwd;
+ getpwuid_r (0, &pwd, buffer,
+ sizeof (buffer));
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_nonposix_getpwuid_r=yes
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_func_nonposix_getpwuid_r=no
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: $ac_cv_func_nonposix_getpwuid_r" >&5
+ echo "${ECHO_T}$ac_cv_func_nonposix_getpwuid_r" >&6
+ if test "$ac_cv_func_nonposix_getpwuid_r" = yes; then
+
+ cat >>confdefs.h <<\_ACEOF
+ #define HAVE_NONPOSIX_GETPWUID_R 1
+ _ACEOF
+
+ fi
+ fi
+ fi
+
+
+
+
+ for ac_func in gethostbyname_r
+ do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_func" >&5
+ echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below. */
+ #include <assert.h>
+ /* Override any gcc2 internal prototype to avoid an error. */
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ /* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+ char $ac_func ();
+ char (*f) ();
+
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ /* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+ choke me
+ #else
+ f = $ac_func;
+ #endif
+
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ eval "$as_ac_var=no"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+ if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+ #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+ _ACEOF
+
+ fi
+ done
+
+ if test "$ac_cv_func_gethostbyname_r" = yes ; then
+ echo "$as_me:$LINENO: checking number of arguments of gethostbyname_r" >&5
+ echo $ECHO_N "checking number of arguments of gethostbyname_r... $ECHO_C" >&6
+ if test "${ol_cv_func_gethostbyname_r_nargs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #define BUFSIZE (sizeof(struct hostent)+10)
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ struct hostent hent; char buffer[BUFSIZE];
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyname_r("localhost", &hent,
+ buffer, bufsize, &h_errno);
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ol_cv_func_gethostbyname_r_nargs5=yes
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ol_cv_func_gethostbyname_r_nargs5=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #define BUFSIZE (sizeof(struct hostent)+10)
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ struct hostent hent;struct hostent *rhent;
+ char buffer[BUFSIZE];
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyname_r("localhost", &hent, buffer, bufsize,
+ &rhent, &h_errno);
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ol_cv_func_gethostbyname_r_nargs6=yes
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ol_cv_func_gethostbyname_r_nargs6=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+
+ if test $ol_cv_func_gethostbyname_r_nargs5 = yes -a \
+ $ol_cv_func_gethostbyname_r_nargs6 = no ; then
+
+ ol_cv_func_gethostbyname_r_nargs=5
+
+ elif test $ol_cv_func_gethostbyname_r_nargs5 = no -a \
+ $ol_cv_func_gethostbyname_r_nargs6 = yes ; then
+
+ ol_cv_func_gethostbyname_r_nargs=6
+
+ else
+ ol_cv_func_gethostbyname_r_nargs=0
+ fi
+
+ fi
+ echo "$as_me:$LINENO: result: $ol_cv_func_gethostbyname_r_nargs" >&5
+ echo "${ECHO_T}$ol_cv_func_gethostbyname_r_nargs" >&6
+ if test $ol_cv_func_gethostbyname_r_nargs -gt 1 ; then
+
+ cat >>confdefs.h <<_ACEOF
+ #define GETHOSTBYNAME_R_NARGS $ol_cv_func_gethostbyname_r_nargs
+ _ACEOF
+
+ fi
+
+ else
+ ol_cv_func_gethostbyname_r_nargs=0
+ fi
+
# BSD/OS & NetBSD use a custom fseeko/ftello built on fsetpos/fgetpos
# We override the previous test that said fseeko/ftello didn't exist
# OS tests are also done in include/c.h and port/fseeko.c
Index: configure.in
===================================================================
RCS file: /projects/cvsroot/pgsql-server/configure.in,v
retrieving revision 1.230
diff -c -r1.230 configure.in
*** configure.in 2003/01/07 06:43:20 1.230
--- configure.in 2003/01/09 13:59:13
***************
*** 846,851 ****
--- 846,956 ----
AC_REPLACE_FUNCS([fseeko gethostname getopt_long getrusage inet_aton random srandom strcasecmp strdup strerror strtol strtoul])
+ AC_FUNC_STRERROR_R
+
+ AC_CHECK_FUNCS(crypt_r)
+
+ if test "$ac_cv_header_pwd_h" = "yes"; then
+ AC_CACHE_CHECK([for posix getpwuid_r],
+ ac_cv_func_posix_getpwuid_r,
+ [AC_TRY_RUN([
+ #define _THREAD_SAFE
+ #define _REENTRANT
+ #define _POSIX_PTHREAD_SEMANTICS
+ #include <errno.h>
+ #include <pwd.h>
+ int main () {
+ char buffer[10000];
+ struct passwd pwd, *pwptr = &pwd;
+ int error;
+ errno = 0;
+ error = getpwuid_r (0, &pwd, buffer,
+ sizeof (buffer), &pwptr);
+ return (error < 0 && errno == ENOSYS)
+ || error == ENOSYS;
+ } ],
+ [ac_cv_func_posix_getpwuid_r=yes],
+ [ac_cv_func_posix_getpwuid_r=no])])
+ if test "$ac_cv_func_posix_getpwuid_r" = yes; then
+ AC_DEFINE(HAVE_POSIX_GETPWUID_R,1,
+ [Have POSIX function getpwuid_r])
+ else
+ AC_CACHE_CHECK([for nonposix getpwuid_r],
+ ac_cv_func_nonposix_getpwuid_r,
+ [AC_TRY_LINK([#include <pwd.h>],
+ [char buffer[10000];
+ struct passwd pwd;
+ getpwuid_r (0, &pwd, buffer,
+ sizeof (buffer));],
+ [ac_cv_func_nonposix_getpwuid_r=yes],
+ [ac_cv_func_nonposix_getpwuid_r=no])])
+ if test "$ac_cv_func_nonposix_getpwuid_r" = yes; then
+ AC_DEFINE(HAVE_NONPOSIX_GETPWUID_R,1,
+ [Have non-POSIX function getpwuid_r])
+ fi
+ fi
+ fi
+
+
+ dnl ====================================================================
+ dnl check no of arguments for gethostbyname_r
+ AC_DEFUN(OL_FUNC_GETHOSTBYNAME_R_NARGS,
+ [AC_CACHE_CHECK(number of arguments of gethostbyname_r,
+ ol_cv_func_gethostbyname_r_nargs,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #define BUFSIZE (sizeof(struct hostent)+10)],
+ [struct hostent hent; char buffer[BUFSIZE];
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyname_r("localhost", &hent,
+ buffer, bufsize, &h_errno);],
+ ol_cv_func_gethostbyname_r_nargs5=yes,
+ ol_cv_func_gethostbyname_r_nargs5=no)
+
+ AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #define BUFSIZE (sizeof(struct hostent)+10)],
+ [struct hostent hent;struct hostent *rhent;
+ char buffer[BUFSIZE];
+ int bufsize=BUFSIZE;int h_errno;
+ (void)gethostbyname_r("localhost", &hent, buffer, bufsize,
+ &rhent, &h_errno);],
+ ol_cv_func_gethostbyname_r_nargs6=yes,
+ ol_cv_func_gethostbyname_r_nargs6=no)
+
+ if test $ol_cv_func_gethostbyname_r_nargs5 = yes -a \
+ $ol_cv_func_gethostbyname_r_nargs6 = no ; then
+
+ ol_cv_func_gethostbyname_r_nargs=5
+
+ elif test $ol_cv_func_gethostbyname_r_nargs5 = no -a \
+ $ol_cv_func_gethostbyname_r_nargs6 = yes ; then
+
+ ol_cv_func_gethostbyname_r_nargs=6
+
+ else
+ ol_cv_func_gethostbyname_r_nargs=0
+ fi
+ ])
+ if test $ol_cv_func_gethostbyname_r_nargs -gt 1 ; then
+ AC_DEFINE_UNQUOTED(GETHOSTBYNAME_R_NARGS,
+ $ol_cv_func_gethostbyname_r_nargs,
+ [set to the number of arguments gethostbyname_r() expects])
+ fi
+ ])dnl
+ dnl
+
+ AC_CHECK_FUNCS(gethostbyname_r)
+ if test "$ac_cv_func_gethostbyname_r" = yes ; then
+ OL_FUNC_GETHOSTBYNAME_R_NARGS
+ else
+ ol_cv_func_gethostbyname_r_nargs=0
+ fi
+
# BSD/OS & NetBSD use a custom fseeko/ftello built on fsetpos/fgetpos
# We override the previous test that said fseeko/ftello didn't exist
# OS tests are also done in include/c.h and port/fseeko.c
Index: src/include/pg_config.h.in
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/pg_config.h.in,v
retrieving revision 1.37
diff -c -r1.37 pg_config.h.in
*** src/include/pg_config.h.in 2003/01/06 06:07:20 1.37
--- src/include/pg_config.h.in 2003/01/09 13:59:14
***************
*** 426,431 ****
--- 426,452 ----
/* Set to 1 if you have strerror() */
#undef HAVE_STRERROR
+ /* Set to 1 if you have strerror_r() */
+ #undef HAVE_STRERROR_R
+
+ /* Set to 1 if strerror_r() returns 'char *' */
+ #undef STRERROR_R_CHAR_P
+
+ /* Set to 1 if you have crypt_r() */
+ #undef HAVE_CRYPT_R
+
+ /* Set to 1 if you have POSIX getpwuid_r() */
+ #undef HAVE_POSIX_GETPWUID_R
+
+ /* Set to 1 if you have non-POSIX getpwuid_r(), returning 'struct passwd*' */
+ #undef HAVE_NONPOSIX_GETPWUID_R
+
+ /* Set to 1 if you have gethostbyname_r() */
+ #undef HAVE_GETHOSTBYNAME_R
+
+ /* Set to the number of paramters gethostbyname_r() takes */
+ #undef GETHOSTBYNAME_R_NARGS
+
/* Set to 1 if you have isinf() */
#undef HAVE_ISINF
diffs-libpq.txtapplication/octet-streamDownload
Index: src/backend/libpq/ip.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/ip.c,v
retrieving revision 1.1
diff -c -r1.1 ip.c
*** src/backend/libpq/ip.c 2003/01/06 03:18:26 1.1
--- src/backend/libpq/ip.c 2003/01/09 13:59:19
***************
*** 44,49 ****
--- 44,61 ----
#define LOG stderr
#endif
+ #if !defined HAVE_IPV6
+ # if defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 6
+ # define pqGethostbyname gethostbyname_r
+ # else
+ static int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno);
+ # endif /* HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 6 */
+ #endif /* !defined HAVE_IPV6 */
+
#if defined(HAVE_UNIX_SOCKETS) && defined(HAVE_IPV6)
static int getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
struct addrinfo **result);
***************
*** 80,88 ****
result->in.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
! struct hostent *hp;
! hp = gethostbyname(hostname);
if ((hp == NULL) || (hp->h_addrtype != AF_INET))
{
elog(LOG, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
--- 92,108 ----
result->in.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
! struct hostent *hp = NULL;
! #ifdef FRONTEND
! struct hostent hpstr;
! char buf[BUFSIZ];
! int herrno = 0;
! pqGethostbyname(hostname, &hpstr, buf, sizeof(buf),
! &hp, &herrno);
! #else
! hp = gethostbyname(hostname);
! #endif
if ((hp == NULL) || (hp->h_addrtype != AF_INET))
{
elog(LOG, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
***************
*** 369,371 ****
--- 389,424 ----
SockAddr_ntop(src, addr_str, INET6_ADDRSTRLEN, 0);
}
#endif
+
+ #if !defined HAVE_IPV6
+ # if defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 6
+ /* macro above */
+ # elif defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 5
+ static int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno)
+ {
+ *result = gethostbyname_r(name, resbuf, buf, buflen, herrno);
+ return( (*result == NULL) ? -1 : 0 );
+ }
+ # else
+ /* either we don't have gethostbyname_r, or it's not a version he handle */
+ static int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno)
+ {
+ *result = gethostbyname(name);
+ if( *result != NULL )
+ return( 0 );
+ else
+ {
+ *herrno = h_errno;
+ return( -1 );
+ }
+ }
+ # endif /* HAVE_GETHOSTBYNAME_R */
+ #endif /* !defined HAVE_IPV6 */
Index: src/interfaces/libpq/fe-auth.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-auth.c,v
retrieving revision 1.72
diff -c -r1.72 fe-auth.c
*** src/interfaces/libpq/fe-auth.c 2002/12/03 22:09:20 1.72
--- src/interfaces/libpq/fe-auth.c 2003/01/09 13:59:19
***************
*** 28,33 ****
--- 28,37 ----
*
*/
+ #define _THREAD_SAFE
+ #define _REENTRANT
+ #define _POSIX_PTHREAD_SEMANTICS
+
#include "postgres_fe.h"
#ifdef WIN32
***************
*** 391,398 ****
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), strerror(errno));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
--- 395,404 ----
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrError(errno, sebuf, sizeof(sebuf)));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
***************
*** 436,444 ****
if (fcntl(sock, F_SETFL, (long) flags))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! strerror(errno));
ret = STATUS_ERROR;
}
--- 442,452 ----
if (fcntl(sock, F_SETFL, (long) flags))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! pqStrError(errno, sebuf, sizeof(sebuf)));
ret = STATUS_ERROR;
}
***************
*** 495,502 ****
if (sendmsg(conn->sock, &msg, 0) == -1)
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n", strerror(errno));
return STATUS_ERROR;
}
return STATUS_OK;
--- 503,513 ----
if (sendmsg(conn->sock, &msg, 0) == -1)
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n",
! pqStrError(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
***************
*** 512,517 ****
--- 523,532 ----
{
int ret;
char *crypt_pwd;
+ #if defined HAVE_CRYPT_R && defined __USE_GNU
+ struct crypt_data cryptbuf;
+ cryptbuf.initialized = 0;
+ #endif
/* Encrypt the password if needed. */
***************
*** 549,555 ****
--- 564,574 ----
char salt[3];
StrNCpy(salt, conn->cryptSalt, 3);
+ #if defined HAVE_CRYPT_R && defined __USE_GNU
+ crypt_pwd = crypt_r(password, salt, &cryptbuf);
+ #else
crypt_pwd = crypt(password, salt);
+ #endif
break;
}
case AUTH_REQ_PASSWORD:
***************
*** 724,733 ****
if (GetUserName(username, &namesize))
name = username;
#else
! struct passwd *pw = getpwuid(geteuid());
!
! if (pw)
! name = pw->pw_name;
#endif
}
--- 743,755 ----
if (GetUserName(username, &namesize))
name = username;
#else
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pw = NULL;
!
! if( pqGetpwuid(geteuid(), &pwdstr,
! pwdbuf, sizeof(pwdbuf), &pw) == 0 )
! name = pw->pw_name;
#endif
}
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.221
diff -c -r1.221 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 2003/01/08 21:33:27 1.221
--- src/interfaces/libpq/fe-connect.c 2003/01/09 13:59:19
***************
*** 716,724 ****
if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) < 0)
#endif
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 716,726 ----
if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) < 0)
#endif
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 740,748 ****
(char *) &on,
sizeof(on)) < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 742,752 ----
(char *) &on,
sizeof(on)) < 0)
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 758,763 ****
--- 762,769 ----
static void
connectFailureMessage(PGconn *conn, int errorno)
{
+ char sebuf[256];
+
if (conn->raddr.sa.sa_family == AF_UNIX)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
***************
*** 765,771 ****
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno),
conn->raddr.un.sun_path);
else
printfPQExpBuffer(&conn->errorMessage,
--- 771,777 ----
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->raddr.un.sun_path);
else
printfPQExpBuffer(&conn->errorMessage,
***************
*** 774,780 ****
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno),
conn->pghost
? conn->pghost
: (conn->pghostaddr
--- 780,786 ----
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->pghost
? conn->pghost
: (conn->pghostaddr
***************
*** 797,802 ****
--- 803,809 ----
int portnum;
int sockfd;
char portstr[64];
+ char sebuf[256];
#ifdef USE_SSL
StartupPacket np; /* Used to negotiate SSL connection */
char SSLok;
***************
*** 1013,1019 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
else
--- 1020,1026 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
else
***************
*** 1036,1042 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
retry2:
--- 1043,1049 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
retry2:
***************
*** 1049,1055 ****
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
if (SSLok == 'S')
--- 1056,1062 ----
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
if (SSLok == 'S')
***************
*** 1234,1239 ****
--- 1241,1247 ----
PQconnectPoll(PGconn *conn)
{
PGresult *res;
+ char sebuf[256];
if (conn == NULL)
return PGRES_POLLING_FAILED;
***************
*** 1309,1315 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
else if (optval != 0)
--- 1317,1323 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
else if (optval != 0)
***************
*** 1329,1335 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1337,1343 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 1368,1374 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1376,1382 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 2186,2191 ****
--- 2194,2200 ----
{
int save_errno = SOCK_ERRNO;
int tmpsock = -1;
+ char sebuf[256];
struct
{
uint32 packetlen;
***************
*** 2264,2270 ****
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
--- 2273,2279 ----
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
***************
*** 2392,2399 ****
*val;
int found_keyword;
! key = strtok(line, "=");
! if (key == NULL)
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
--- 2401,2409 ----
*val;
int found_keyword;
! key = line;
! val = strchr(line, '=');
! if( val == NULL )
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
***************
*** 2402,2407 ****
--- 2412,2418 ----
fclose(f);
return 3;
}
+ *val++ = '\0';
/*
* If not already set, set the database name to the
***************
*** 2411,2418 ****
if (strcmp(options[i].keyword, "dbname") == 0)
if (options[i].val == NULL)
options[i].val = strdup(service);
-
- val = line + strlen(line) + 1;
found_keyword = 0;
for (i = 0; options[i].keyword; i++)
--- 2422,2427 ----
Index: src/interfaces/libpq/fe-lobj.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-lobj.c,v
retrieving revision 1.41
diff -c -r1.41 fe-lobj.c
*** src/interfaces/libpq/fe-lobj.c 2002/06/20 20:29:54 1.41
--- src/interfaces/libpq/fe-lobj.c 2003/01/09 13:59:19
***************
*** 396,404 ****
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
return InvalidOid;
}
--- 396,405 ----
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrError(errno, sebuf, sizeof(sebuf)));
return InvalidOid;
}
***************
*** 479,487 ****
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
(void) lo_close(conn, lobj);
return -1;
}
--- 480,489 ----
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrError(errno, sebuf, sizeof(sebuf)));
(void) lo_close(conn, lobj);
return -1;
}
Index: src/interfaces/libpq/fe-misc.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-misc.c,v
retrieving revision 1.86
diff -c -r1.86 fe-misc.c
*** src/interfaces/libpq/fe-misc.c 2003/01/07 22:23:17 1.86
--- src/interfaces/libpq/fe-misc.c 2003/01/09 13:59:19
***************
*** 381,393 ****
if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
&timeout) < 0)
{
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry1;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 381,394 ----
if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
&timeout) < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry1;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 415,427 ****
if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
&timeout) < 0)
{
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry2;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
--- 416,429 ----
if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
&timeout) < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry2;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
***************
*** 443,448 ****
--- 445,451 ----
{
int someread = 0;
int nread;
+ char sebuf[256];
if (conn->sock < 0)
{
***************
*** 513,519 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 516,522 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 593,599 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 596,602 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 654,659 ****
--- 657,663 ----
while (len > 0)
{
int sent;
+ char sebuf[256];
sent = pqsecure_write(conn, ptr, len);
***************
*** 700,706 ****
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
/* We don't assume it's a fatal error... */
return -1;
}
--- 704,710 ----
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
/* We don't assume it's a fatal error... */
return -1;
}
***************
*** 850,860 ****
&except_mask, ptmp_timeout);
if (selresult < 0)
{
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return EOF;
}
if (selresult == 0)
--- 854,865 ----
&except_mask, ptmp_timeout);
if (selresult < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return EOF;
}
if (selresult == 0)
***************
*** 917,919 ****
--- 922,970 ----
}
#endif /* ENABLE_NLS */
+
+
+ /*
+ * Wrapper around strerror and strerror_r to use the former if it is
+ * available and also return a more useful value (the error string).
+ */
+ char *pqStrError(int errnum, char *strerrbuf, size_t buflen)
+ {
+ #if defined HAVE_STRERROR_R && defined STRERROR_R_CHAR_P
+ /* broken strerror_r which returns 'char *' */
+ return( strerror_r(errnum, strerrbuf, buflen) );
+ #elif defined HAVE_STRERROR_R
+ /* reentrant strerror_r */
+ (void)strerror_r(errnum, strerrbuf, buflen);
+ return( strerrbuf );
+ #else
+ /* no strerror_r available, just use strerror */
+ return( strerror(errnum) );
+ #endif
+ }
+
+ #if defined HAVE_NONPOSIX_GETPWUID_R
+ int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result)
+ {
+ fprintf(stderr, "pqGetpwuid(2)\n");
+ *result = getpwuid_r(uid, resultbuf, buffer, buflen);
+
+ if( result == NULL )
+ return( -1 );
+ else
+ return( 0 );
+ }
+ #elif !defined HAVE_POSIX_GETPWUID_R
+ int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result)
+ {
+ fprintf(stderr, "pqGetpwuid(38)\n");
+ *result = getpwuid(uid);
+
+ if( result == NULL )
+ return( -1 );
+ else
+ return( 0 );
+ }
+ #endif
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.20
diff -c -r1.20 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 2003/01/08 23:18:25 1.20
--- src/interfaces/libpq/fe-secure.c 2003/01/09 13:59:19
***************
*** 272,280 ****
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
--- 272,283 ----
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! {
! char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! }
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
***************
*** 319,327 ****
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
--- 322,333 ----
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! {
! char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! }
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
***************
*** 385,393 ****
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 391,400 ----
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 465,478 ****
static DH *
load_dh_file(int keylength)
{
! struct passwd *pwd;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if ((pwd = getpwuid(getuid())) == NULL)
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
--- 472,487 ----
static DH *
load_dh_file(int keylength)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
***************
*** 605,619 ****
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! struct passwd *pwd;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
! if ((pwd = getpwuid(getuid())) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
--- 614,632 ----
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
+ char sebuf[256];
+
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
***************
*** 629,635 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
--- 642,648 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, pqStrError(errno, sebuf, sizeof(sebuf)));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
***************
*** 665,671 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, strerror(errno));
X509_free(*x509);
return -1;
}
--- 678,684 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, pqStrError(errno, sebuf, sizeof(sebuf)));
X509_free(*x509);
return -1;
}
***************
*** 709,715 ****
initialize_SSL(PGconn *conn)
{
struct stat buf;
! struct passwd *pwd;
char fnbuf[2048];
if (!SSL_context)
--- 722,730 ----
initialize_SSL(PGconn *conn)
{
struct stat buf;
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
char fnbuf[2048];
if (!SSL_context)
***************
*** 726,732 ****
}
}
! if ((pwd = getpwuid(getuid())) != NULL)
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
--- 741,747 ----
}
}
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
***************
*** 734,743 ****
{
return 0;
#ifdef NOT_USED
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
#endif
}
--- 749,759 ----
{
return 0;
#ifdef NOT_USED
+ char sebuf[256];
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, pqStrError(errno, sebuf, sizeof(sebuf)));
return -1;
#endif
}
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.60
diff -c -r1.60 libpq-int.h
*** src/interfaces/libpq/libpq-int.h 2002/10/16 02:55:30 1.60
--- src/interfaces/libpq/libpq-int.h 2003/01/09 13:59:19
***************
*** 20,31 ****
--- 20,39 ----
#ifndef LIBPQ_INT_H
#define LIBPQ_INT_H
+ #define _THREAD_SAFE
+ #define _REENTRANT
+ #define _POSIX_PTHREAD_SEMANTICS
+
#include <time.h>
#include <sys/types.h>
#ifndef WIN32
#include <sys/time.h>
#endif
+ #ifdef HAVE_PWD_H
+ # include <pwd.h>
+ #endif
+
#if defined(WIN32) && (!defined(ssize_t))
typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast
* not VC6) */
***************
*** 345,350 ****
--- 353,378 ----
extern int pqReadReady(PGconn *conn);
extern int pqWriteReady(PGconn *conn);
+ /* routines to aid thread safety */
+ extern char *pqStrError(int errnum, char *strerrbuf, size_t buflen);
+
+ #if defined HAVE_POSIX_GETPWUID_R
+ # define pqGetpwuid getpwuid_r
+ #else
+ extern int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result);
+ #endif
+
+ #if !defined HAVE_GETHOSTBYNAME_R || (defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS < 6)
+ extern int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno);
+ #else
+ #define pqGethostbyname gethostbyname_r
+ #endif
+
/* === in fe-secure.c === */
extern int pqsecure_initialize(PGconn *);
***************
*** 389,395 ****
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR strerror
#endif
#endif /* LIBPQ_INT_H */
--- 417,423 ----
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR pqStrError
#endif
#endif /* LIBPQ_INT_H */
Index: src/interfaces/libpq/win32.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/win32.c,v
retrieving revision 1.4
diff -c -r1.4 win32.c
*** src/interfaces/libpq/win32.c 2002/09/04 20:31:47 1.4
--- src/interfaces/libpq/win32.c 2003/01/09 13:59:19
***************
*** 271,283 ****
*/
const char *
! winsock_strerror(int err)
{
- static char buf[512]; /* Not threadsafe */
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, buf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
--- 271,282 ----
*/
const char *
! winsock_strerror(int err, char *strerrbuf, size_t buflen)
{
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, strerrbuf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
***************
*** 302,321 ****
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! buf, sizeof(buf) - 64,
0
);
}
if (!success)
! sprintf(buf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! buf[sizeof(buf) - 1] = '\0';
! offs = strlen(buf);
! if (offs > sizeof(buf) - 64)
! offs = sizeof(buf) - 64;
! sprintf(buf + offs, " (0x%08X/%lu)", err, err);
}
! return buf;
}
--- 301,320 ----
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! strerrbuf, buflen - 64,
0
);
}
if (!success)
! sprintf(strerrbuf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! strerrbuf[buflen - 1] = '\0';
! offs = strlen(strerrbuf);
! if (offs > buflen - 64)
! offs = buflen - 64;
! sprintf(strerrbuf + offs, " (0x%08X/%lu)", err, err);
}
! return strerrbuf;
}
Guys, just posted patches for libpq to address thread-safe issues. Now
uses strerror_r(), gethostbyname_r(), getpwuid_r() and crypt_r() where
available. Passes all tests on Linux and Solaris.
Any comments let me know - my first major(ish) outing in the
PostgreSQL source, in particular I'm not use in the configure stuff is
100% right...
Patches also at:
http://services.csl.co.uk/postgresql/diffs-20030109-configure.txt.gz
http://services.csl.co.uk/postgresql/diffs-20030109-libpq.txt.gz
Thanks, Lee.
Lee Kindness writes:
Show quoted text
Tom Lane writes:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
We have definatly had requests for improved thread-safeness for libpq
and ecpg in the past, so whatever you can do would be a help. We say
libpq is thread-safe, but specifically mention the non-threadsafe calls
in the libpq documentation, or at least we should.We do:
http://www.ca.postgresql.org/users-lounge/docs/7.3/postgres/libpq-threading.html
But Lee's point about depending on possibly-unsafe libc routines is a
good one. I don't think anyone's gone through the code with an eye to
that.Right, so a reasonable angle for me to take is to go through the libpq
source looking for potential problem areas and use of "known bad"
functions. I can add autoconf checks for the replacement *_r()
functions, and use these in place of the traditional ones where
available.If any function is found to be not thread-safe and cannot be made so
using standard library calls then it needs to be documented as such
both in the source and the aforementioned documentation.This approach avoids any thread library dependencies and documents the
current state of play WRT thread safety (i.e it's a good, and needed,
basis for any later work).ECPG is a separate issue, and best handled as such (it will need
thread calls). I'll post a patch for it at a later date so the changes
are available to anyone who wants to play with ECPG and threads.Ta, Lee.
Lee Kindness <lkindness@csl.co.uk> writes:
+ #define _THREAD_SAFE + #define _REENTRANT + #define _POSIX_PTHREAD_SEMANTICS
What is this stuff, and why isn't it wrapped in any sort of
platform-specific test? If it's needed, why is it in only one .c file?
Also, haven't you broken SOCK_STRERROR for the Windows case?
regards, tom lane
Tom,
Tom Lane writes:
Lee Kindness <lkindness@csl.co.uk> writes:
+ #define _THREAD_SAFE + #define _REENTRANT + #define _POSIX_PTHREAD_SEMANTICSWhat is this stuff, and why isn't it wrapped in any sort of
platform-specific test? If it's needed, why is it in only one .c
file?
It's actually in libpq-int.h too... The correct way for this is to
compile with the compilers specific thread flags, however the downside
to this has already been discussed. Depending on the system one, or a
combination of those flags will turn on some magic such as errno being
a function call rather than a global variable. This is needed to make
the library thread safe.
On a second look libpq-int.h isn't the best place for this (hence it
also appears in one of the C files), it needs to be done in each C
file before any of the system headers are included - a libpq-threads.h
header? Would this be ok?
Do do things 100% right we'd need to detect compiler thread flags and
compile with them...
Also, haven't you broken SOCK_STRERROR for the Windows case?
Sorry, I seem to have forgotton to update the prototype in win32.h to
match the updated function. Updated diff attached (and online).
Lee.
Attachments:
diffs-libpq.txtapplication/octet-streamDownload
Index: src/backend/libpq/ip.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/ip.c,v
retrieving revision 1.1
diff -c -r1.1 ip.c
*** src/backend/libpq/ip.c 2003/01/06 03:18:26 1.1
--- src/backend/libpq/ip.c 2003/01/09 15:13:37
***************
*** 44,49 ****
--- 44,61 ----
#define LOG stderr
#endif
+ #if !defined HAVE_IPV6
+ # if defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 6
+ # define pqGethostbyname gethostbyname_r
+ # else
+ static int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno);
+ # endif /* HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 6 */
+ #endif /* !defined HAVE_IPV6 */
+
#if defined(HAVE_UNIX_SOCKETS) && defined(HAVE_IPV6)
static int getaddrinfo_unix(const char *path, const struct addrinfo *hintsp,
struct addrinfo **result);
***************
*** 80,88 ****
result->in.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
! struct hostent *hp;
! hp = gethostbyname(hostname);
if ((hp == NULL) || (hp->h_addrtype != AF_INET))
{
elog(LOG, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
--- 92,108 ----
result->in.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
! struct hostent *hp = NULL;
! #ifdef FRONTEND
! struct hostent hpstr;
! char buf[BUFSIZ];
! int herrno = 0;
! pqGethostbyname(hostname, &hpstr, buf, sizeof(buf),
! &hp, &herrno);
! #else
! hp = gethostbyname(hostname);
! #endif
if ((hp == NULL) || (hp->h_addrtype != AF_INET))
{
elog(LOG, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
***************
*** 369,371 ****
--- 389,424 ----
SockAddr_ntop(src, addr_str, INET6_ADDRSTRLEN, 0);
}
#endif
+
+ #if !defined HAVE_IPV6
+ # if defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 6
+ /* macro above */
+ # elif defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS == 5
+ static int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno)
+ {
+ *result = gethostbyname_r(name, resbuf, buf, buflen, herrno);
+ return( (*result == NULL) ? -1 : 0 );
+ }
+ # else
+ /* either we don't have gethostbyname_r, or it's not a version he handle */
+ static int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno)
+ {
+ *result = gethostbyname(name);
+ if( *result != NULL )
+ return( 0 );
+ else
+ {
+ *herrno = h_errno;
+ return( -1 );
+ }
+ }
+ # endif /* HAVE_GETHOSTBYNAME_R */
+ #endif /* !defined HAVE_IPV6 */
Index: src/interfaces/libpq/fe-auth.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-auth.c,v
retrieving revision 1.72
diff -c -r1.72 fe-auth.c
*** src/interfaces/libpq/fe-auth.c 2002/12/03 22:09:20 1.72
--- src/interfaces/libpq/fe-auth.c 2003/01/09 15:13:37
***************
*** 28,33 ****
--- 28,37 ----
*
*/
+ #define _THREAD_SAFE
+ #define _REENTRANT
+ #define _POSIX_PTHREAD_SEMANTICS
+
#include "postgres_fe.h"
#ifdef WIN32
***************
*** 391,398 ****
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), strerror(errno));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
--- 395,404 ----
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrError(errno, sebuf, sizeof(sebuf)));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
***************
*** 436,444 ****
if (fcntl(sock, F_SETFL, (long) flags))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! strerror(errno));
ret = STATUS_ERROR;
}
--- 442,452 ----
if (fcntl(sock, F_SETFL, (long) flags))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! pqStrError(errno, sebuf, sizeof(sebuf)));
ret = STATUS_ERROR;
}
***************
*** 495,502 ****
if (sendmsg(conn->sock, &msg, 0) == -1)
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n", strerror(errno));
return STATUS_ERROR;
}
return STATUS_OK;
--- 503,513 ----
if (sendmsg(conn->sock, &msg, 0) == -1)
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n",
! pqStrError(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
***************
*** 512,517 ****
--- 523,532 ----
{
int ret;
char *crypt_pwd;
+ #if defined HAVE_CRYPT_R && defined __USE_GNU
+ struct crypt_data cryptbuf;
+ cryptbuf.initialized = 0;
+ #endif
/* Encrypt the password if needed. */
***************
*** 549,555 ****
--- 564,574 ----
char salt[3];
StrNCpy(salt, conn->cryptSalt, 3);
+ #if defined HAVE_CRYPT_R && defined __USE_GNU
+ crypt_pwd = crypt_r(password, salt, &cryptbuf);
+ #else
crypt_pwd = crypt(password, salt);
+ #endif
break;
}
case AUTH_REQ_PASSWORD:
***************
*** 724,733 ****
if (GetUserName(username, &namesize))
name = username;
#else
! struct passwd *pw = getpwuid(geteuid());
!
! if (pw)
! name = pw->pw_name;
#endif
}
--- 743,755 ----
if (GetUserName(username, &namesize))
name = username;
#else
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pw = NULL;
!
! if( pqGetpwuid(geteuid(), &pwdstr,
! pwdbuf, sizeof(pwdbuf), &pw) == 0 )
! name = pw->pw_name;
#endif
}
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.221
diff -c -r1.221 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 2003/01/08 21:33:27 1.221
--- src/interfaces/libpq/fe-connect.c 2003/01/09 15:13:37
***************
*** 716,724 ****
if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) < 0)
#endif
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 716,726 ----
if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) < 0)
#endif
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 740,748 ****
(char *) &on,
sizeof(on)) < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 742,752 ----
(char *) &on,
sizeof(on)) < 0)
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 758,763 ****
--- 762,769 ----
static void
connectFailureMessage(PGconn *conn, int errorno)
{
+ char sebuf[256];
+
if (conn->raddr.sa.sa_family == AF_UNIX)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
***************
*** 765,771 ****
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno),
conn->raddr.un.sun_path);
else
printfPQExpBuffer(&conn->errorMessage,
--- 771,777 ----
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->raddr.un.sun_path);
else
printfPQExpBuffer(&conn->errorMessage,
***************
*** 774,780 ****
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno),
conn->pghost
? conn->pghost
: (conn->pghostaddr
--- 780,786 ----
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->pghost
? conn->pghost
: (conn->pghostaddr
***************
*** 797,802 ****
--- 803,809 ----
int portnum;
int sockfd;
char portstr[64];
+ char sebuf[256];
#ifdef USE_SSL
StartupPacket np; /* Used to negotiate SSL connection */
char SSLok;
***************
*** 1013,1019 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
else
--- 1020,1026 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
else
***************
*** 1036,1042 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
retry2:
--- 1043,1049 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
retry2:
***************
*** 1049,1055 ****
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
if (SSLok == 'S')
--- 1056,1062 ----
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
if (SSLok == 'S')
***************
*** 1234,1239 ****
--- 1241,1247 ----
PQconnectPoll(PGconn *conn)
{
PGresult *res;
+ char sebuf[256];
if (conn == NULL)
return PGRES_POLLING_FAILED;
***************
*** 1309,1315 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
else if (optval != 0)
--- 1317,1323 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
else if (optval != 0)
***************
*** 1329,1335 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1337,1343 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 1368,1374 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1376,1382 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 2186,2191 ****
--- 2194,2200 ----
{
int save_errno = SOCK_ERRNO;
int tmpsock = -1;
+ char sebuf[256];
struct
{
uint32 packetlen;
***************
*** 2264,2270 ****
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
--- 2273,2279 ----
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
***************
*** 2392,2399 ****
*val;
int found_keyword;
! key = strtok(line, "=");
! if (key == NULL)
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
--- 2401,2409 ----
*val;
int found_keyword;
! key = line;
! val = strchr(line, '=');
! if( val == NULL )
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
***************
*** 2402,2407 ****
--- 2412,2418 ----
fclose(f);
return 3;
}
+ *val++ = '\0';
/*
* If not already set, set the database name to the
***************
*** 2411,2418 ****
if (strcmp(options[i].keyword, "dbname") == 0)
if (options[i].val == NULL)
options[i].val = strdup(service);
-
- val = line + strlen(line) + 1;
found_keyword = 0;
for (i = 0; options[i].keyword; i++)
--- 2422,2427 ----
Index: src/interfaces/libpq/fe-lobj.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-lobj.c,v
retrieving revision 1.41
diff -c -r1.41 fe-lobj.c
*** src/interfaces/libpq/fe-lobj.c 2002/06/20 20:29:54 1.41
--- src/interfaces/libpq/fe-lobj.c 2003/01/09 15:13:37
***************
*** 396,404 ****
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
return InvalidOid;
}
--- 396,405 ----
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrError(errno, sebuf, sizeof(sebuf)));
return InvalidOid;
}
***************
*** 479,487 ****
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
(void) lo_close(conn, lobj);
return -1;
}
--- 480,489 ----
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrError(errno, sebuf, sizeof(sebuf)));
(void) lo_close(conn, lobj);
return -1;
}
Index: src/interfaces/libpq/fe-misc.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-misc.c,v
retrieving revision 1.86
diff -c -r1.86 fe-misc.c
*** src/interfaces/libpq/fe-misc.c 2003/01/07 22:23:17 1.86
--- src/interfaces/libpq/fe-misc.c 2003/01/09 15:13:37
***************
*** 381,393 ****
if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
&timeout) < 0)
{
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry1;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 381,394 ----
if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
&timeout) < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry1;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 415,427 ****
if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
&timeout) < 0)
{
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry2;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
--- 416,429 ----
if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
&timeout) < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry2;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
***************
*** 443,448 ****
--- 445,451 ----
{
int someread = 0;
int nread;
+ char sebuf[256];
if (conn->sock < 0)
{
***************
*** 513,519 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 516,522 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 593,599 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 596,602 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 654,659 ****
--- 657,663 ----
while (len > 0)
{
int sent;
+ char sebuf[256];
sent = pqsecure_write(conn, ptr, len);
***************
*** 700,706 ****
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
/* We don't assume it's a fatal error... */
return -1;
}
--- 704,710 ----
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
/* We don't assume it's a fatal error... */
return -1;
}
***************
*** 850,860 ****
&except_mask, ptmp_timeout);
if (selresult < 0)
{
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return EOF;
}
if (selresult == 0)
--- 854,865 ----
&except_mask, ptmp_timeout);
if (selresult < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return EOF;
}
if (selresult == 0)
***************
*** 917,919 ****
--- 922,970 ----
}
#endif /* ENABLE_NLS */
+
+
+ /*
+ * Wrapper around strerror and strerror_r to use the former if it is
+ * available and also return a more useful value (the error string).
+ */
+ char *pqStrError(int errnum, char *strerrbuf, size_t buflen)
+ {
+ #if defined HAVE_STRERROR_R && defined STRERROR_R_CHAR_P
+ /* broken strerror_r which returns 'char *' */
+ return( strerror_r(errnum, strerrbuf, buflen) );
+ #elif defined HAVE_STRERROR_R
+ /* reentrant strerror_r */
+ (void)strerror_r(errnum, strerrbuf, buflen);
+ return( strerrbuf );
+ #else
+ /* no strerror_r available, just use strerror */
+ return( strerror(errnum) );
+ #endif
+ }
+
+ #if defined HAVE_NONPOSIX_GETPWUID_R
+ int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result)
+ {
+ fprintf(stderr, "pqGetpwuid(2)\n");
+ *result = getpwuid_r(uid, resultbuf, buffer, buflen);
+
+ if( result == NULL )
+ return( -1 );
+ else
+ return( 0 );
+ }
+ #elif !defined HAVE_POSIX_GETPWUID_R
+ int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result)
+ {
+ fprintf(stderr, "pqGetpwuid(38)\n");
+ *result = getpwuid(uid);
+
+ if( result == NULL )
+ return( -1 );
+ else
+ return( 0 );
+ }
+ #endif
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.20
diff -c -r1.20 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 2003/01/08 23:18:25 1.20
--- src/interfaces/libpq/fe-secure.c 2003/01/09 15:13:37
***************
*** 272,280 ****
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
--- 272,283 ----
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! {
! char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! }
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
***************
*** 319,327 ****
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
--- 322,333 ----
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! {
! char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! }
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
***************
*** 385,393 ****
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 391,400 ----
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 465,478 ****
static DH *
load_dh_file(int keylength)
{
! struct passwd *pwd;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if ((pwd = getpwuid(getuid())) == NULL)
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
--- 472,487 ----
static DH *
load_dh_file(int keylength)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
***************
*** 605,619 ****
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! struct passwd *pwd;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
! if ((pwd = getpwuid(getuid())) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
--- 614,632 ----
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
+ char sebuf[256];
+
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
***************
*** 629,635 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
--- 642,648 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, pqStrError(errno, sebuf, sizeof(sebuf)));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
***************
*** 665,671 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, strerror(errno));
X509_free(*x509);
return -1;
}
--- 678,684 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, pqStrError(errno, sebuf, sizeof(sebuf)));
X509_free(*x509);
return -1;
}
***************
*** 709,715 ****
initialize_SSL(PGconn *conn)
{
struct stat buf;
! struct passwd *pwd;
char fnbuf[2048];
if (!SSL_context)
--- 722,730 ----
initialize_SSL(PGconn *conn)
{
struct stat buf;
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
char fnbuf[2048];
if (!SSL_context)
***************
*** 726,732 ****
}
}
! if ((pwd = getpwuid(getuid())) != NULL)
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
--- 741,747 ----
}
}
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
***************
*** 734,743 ****
{
return 0;
#ifdef NOT_USED
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
#endif
}
--- 749,759 ----
{
return 0;
#ifdef NOT_USED
+ char sebuf[256];
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, pqStrError(errno, sebuf, sizeof(sebuf)));
return -1;
#endif
}
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.60
diff -c -r1.60 libpq-int.h
*** src/interfaces/libpq/libpq-int.h 2002/10/16 02:55:30 1.60
--- src/interfaces/libpq/libpq-int.h 2003/01/09 15:13:37
***************
*** 20,31 ****
--- 20,39 ----
#ifndef LIBPQ_INT_H
#define LIBPQ_INT_H
+ #define _THREAD_SAFE
+ #define _REENTRANT
+ #define _POSIX_PTHREAD_SEMANTICS
+
#include <time.h>
#include <sys/types.h>
#ifndef WIN32
#include <sys/time.h>
#endif
+ #ifdef HAVE_PWD_H
+ # include <pwd.h>
+ #endif
+
#if defined(WIN32) && (!defined(ssize_t))
typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast
* not VC6) */
***************
*** 345,350 ****
--- 353,378 ----
extern int pqReadReady(PGconn *conn);
extern int pqWriteReady(PGconn *conn);
+ /* routines to aid thread safety */
+ extern char *pqStrError(int errnum, char *strerrbuf, size_t buflen);
+
+ #if defined HAVE_POSIX_GETPWUID_R
+ # define pqGetpwuid getpwuid_r
+ #else
+ extern int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result);
+ #endif
+
+ #if !defined HAVE_GETHOSTBYNAME_R || (defined HAVE_GETHOSTBYNAME_R && GETHOSTBYNAME_R_NARGS < 6)
+ extern int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno);
+ #else
+ #define pqGethostbyname gethostbyname_r
+ #endif
+
/* === in fe-secure.c === */
extern int pqsecure_initialize(PGconn *);
***************
*** 389,395 ****
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR strerror
#endif
#endif /* LIBPQ_INT_H */
--- 417,423 ----
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR pqStrError
#endif
#endif /* LIBPQ_INT_H */
Index: src/interfaces/libpq/win32.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/win32.c,v
retrieving revision 1.4
diff -c -r1.4 win32.c
*** src/interfaces/libpq/win32.c 2002/09/04 20:31:47 1.4
--- src/interfaces/libpq/win32.c 2003/01/09 15:13:37
***************
*** 271,283 ****
*/
const char *
! winsock_strerror(int err)
{
- static char buf[512]; /* Not threadsafe */
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, buf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
--- 271,282 ----
*/
const char *
! winsock_strerror(int err, char *strerrbuf, size_t buflen)
{
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, strerrbuf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
***************
*** 302,321 ****
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! buf, sizeof(buf) - 64,
0
);
}
if (!success)
! sprintf(buf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! buf[sizeof(buf) - 1] = '\0';
! offs = strlen(buf);
! if (offs > sizeof(buf) - 64)
! offs = sizeof(buf) - 64;
! sprintf(buf + offs, " (0x%08X/%lu)", err, err);
}
! return buf;
}
--- 301,320 ----
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! strerrbuf, buflen - 64,
0
);
}
if (!success)
! sprintf(strerrbuf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! strerrbuf[buflen - 1] = '\0';
! offs = strlen(strerrbuf);
! if (offs > buflen - 64)
! offs = buflen - 64;
! sprintf(strerrbuf + offs, " (0x%08X/%lu)", err, err);
}
! return strerrbuf;
}
Index: src/interfaces/libpq/win32.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/win32.h,v
retrieving revision 1.21
diff -c -r1.21 win32.h
*** src/interfaces/libpq/win32.h 2002/12/30 21:07:26 1.21
--- src/interfaces/libpq/win32.h 2003/01/09 15:13:37
***************
*** 42,48 ****
/*
* support for handling Windows Socket errors
*/
! extern const char *winsock_strerror(int eno);
!
#endif
--- 42,47 ----
/*
* support for handling Windows Socket errors
*/
! extern const char *winsock_strerror(int err, char *strerrbuf, size_t buflen);
#endif
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.
AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
--
Peter Eisentraut peter_e@gmx.net
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.
This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.
I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.
Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).
All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Show quoted text
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
Patch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.
Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Show quoted text
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
Attachments:
libpq_r-diffs-20030113.txttext/plainDownload
Index: src/backend/libpq/ip.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/libpq/ip.c,v
retrieving revision 1.2
diff -c -r1.2 ip.c
*** src/backend/libpq/ip.c 2003/01/09 14:35:03 1.2
--- src/backend/libpq/ip.c 2003/01/13 11:59:35
***************
*** 20,25 ****
--- 20,26 ----
#ifndef FRONTEND
#include "postgres.h"
#else
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#endif
***************
*** 80,88 ****
result->in.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
! struct hostent *hp;
! hp = gethostbyname(hostname);
if ((hp == NULL) || (hp->h_addrtype != AF_INET))
{
elog(LOG, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
--- 81,97 ----
result->in.sin_addr.s_addr = htonl(INADDR_ANY);
else
{
! struct hostent *hp = NULL;
! #ifdef FRONTEND
! struct hostent hpstr;
! char buf[BUFSIZ];
! int herrno = 0;
! pqGethostbyname(hostname, &hpstr, buf, sizeof(buf),
! &hp, &herrno);
! #else
! hp = gethostbyname(hostname);
! #endif
if ((hp == NULL) || (hp->h_addrtype != AF_INET))
{
elog(LOG, "getaddrinfo2: gethostbyname(%s) failed\n", hostname);
Index: src/interfaces/libpq/Makefile
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/Makefile,v
retrieving revision 1.72
diff -c -r1.72 Makefile
*** src/interfaces/libpq/Makefile 2003/01/10 10:59:08 1.72
--- src/interfaces/libpq/Makefile 2003/01/13 11:59:35
***************
*** 20,28 ****
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DSYSCONFDIR='"$(sysconfdir)"'
! OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
! pqexpbuffer.o dllist.o pqsignal.o fe-secure.o wchar.o encnames.o ip.o \
! md5.o \
$(filter inet_aton.o snprintf.o strerror.o, $(LIBOBJS))
--- 20,28 ----
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DFRONTEND -DSYSCONFDIR='"$(sysconfdir)"'
! OBJS= libpq-reentrant.o fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o \
! fe-lobj.o pqexpbuffer.o dllist.o pqsignal.o fe-secure.o wchar.o encnames.o \
! ip.o md5.o \
$(filter inet_aton.o snprintf.o strerror.o, $(LIBOBJS))
Index: src/interfaces/libpq/fe-auth.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-auth.c,v
retrieving revision 1.72
diff -c -r1.72 fe-auth.c
*** src/interfaces/libpq/fe-auth.c 2002/12/03 22:09:20 1.72
--- src/interfaces/libpq/fe-auth.c 2003/01/13 11:59:35
***************
*** 28,33 ****
--- 28,34 ----
*
*/
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#ifdef WIN32
***************
*** 391,398 ****
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), strerror(errno));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
--- 392,401 ----
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf)));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
***************
*** 436,444 ****
if (fcntl(sock, F_SETFL, (long) flags))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! strerror(errno));
ret = STATUS_ERROR;
}
--- 439,449 ----
if (fcntl(sock, F_SETFL, (long) flags))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! pqStrerror(errno, sebuf, sizeof(sebuf)));
ret = STATUS_ERROR;
}
***************
*** 495,502 ****
if (sendmsg(conn->sock, &msg, 0) == -1)
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n", strerror(errno));
return STATUS_ERROR;
}
return STATUS_OK;
--- 500,510 ----
if (sendmsg(conn->sock, &msg, 0) == -1)
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n",
! pqStrerror(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
***************
*** 724,733 ****
if (GetUserName(username, &namesize))
name = username;
#else
! struct passwd *pw = getpwuid(geteuid());
!
! if (pw)
! name = pw->pw_name;
#endif
}
--- 732,744 ----
if (GetUserName(username, &namesize))
name = username;
#else
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pw = NULL;
!
! if( pqGetpwuid(geteuid(), &pwdstr,
! pwdbuf, sizeof(pwdbuf), &pw) == 0 )
! name = pw->pw_name;
#endif
}
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.221
diff -c -r1.221 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 2003/01/08 21:33:27 1.221
--- src/interfaces/libpq/fe-connect.c 2003/01/13 11:59:36
***************
*** 13,18 ****
--- 13,19 ----
*-------------------------------------------------------------------------
*/
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#include <sys/types.h>
***************
*** 716,724 ****
if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) < 0)
#endif
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 717,727 ----
if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) < 0)
#endif
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 740,748 ****
(char *) &on,
sizeof(on)) < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 743,753 ----
(char *) &on,
sizeof(on)) < 0)
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 758,763 ****
--- 763,770 ----
static void
connectFailureMessage(PGconn *conn, int errorno)
{
+ char sebuf[256];
+
if (conn->raddr.sa.sa_family == AF_UNIX)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
***************
*** 765,771 ****
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno),
conn->raddr.un.sun_path);
else
printfPQExpBuffer(&conn->errorMessage,
--- 772,778 ----
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->raddr.un.sun_path);
else
printfPQExpBuffer(&conn->errorMessage,
***************
*** 774,780 ****
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno),
conn->pghost
? conn->pghost
: (conn->pghostaddr
--- 781,787 ----
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->pghost
? conn->pghost
: (conn->pghostaddr
***************
*** 797,802 ****
--- 804,810 ----
int portnum;
int sockfd;
char portstr[64];
+ char sebuf[256];
#ifdef USE_SSL
StartupPacket np; /* Used to negotiate SSL connection */
char SSLok;
***************
*** 1013,1019 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
else
--- 1021,1027 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
else
***************
*** 1036,1042 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
retry2:
--- 1044,1050 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
retry2:
***************
*** 1049,1055 ****
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto connect_errReturn;
}
if (SSLok == 'S')
--- 1057,1063 ----
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto connect_errReturn;
}
if (SSLok == 'S')
***************
*** 1234,1239 ****
--- 1242,1248 ----
PQconnectPoll(PGconn *conn)
{
PGresult *res;
+ char sebuf[256];
if (conn == NULL)
return PGRES_POLLING_FAILED;
***************
*** 1309,1315 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
else if (optval != 0)
--- 1318,1324 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
else if (optval != 0)
***************
*** 1329,1335 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1338,1344 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 1368,1374 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1377,1383 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 2186,2191 ****
--- 2195,2201 ----
{
int save_errno = SOCK_ERRNO;
int tmpsock = -1;
+ char sebuf[256];
struct
{
uint32 packetlen;
***************
*** 2264,2270 ****
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
--- 2274,2280 ----
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
***************
*** 2392,2399 ****
*val;
int found_keyword;
! key = strtok(line, "=");
! if (key == NULL)
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
--- 2402,2410 ----
*val;
int found_keyword;
! key = line;
! val = strchr(line, '=');
! if( val == NULL )
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
***************
*** 2402,2407 ****
--- 2413,2419 ----
fclose(f);
return 3;
}
+ *val++ = '\0';
/*
* If not already set, set the database name to the
***************
*** 2411,2418 ****
if (strcmp(options[i].keyword, "dbname") == 0)
if (options[i].val == NULL)
options[i].val = strdup(service);
-
- val = line + strlen(line) + 1;
found_keyword = 0;
for (i = 0; options[i].keyword; i++)
--- 2423,2428 ----
Index: src/interfaces/libpq/fe-exec.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-exec.c,v
retrieving revision 1.124
diff -c -r1.124 fe-exec.c
*** src/interfaces/libpq/fe-exec.c 2003/01/07 22:23:17 1.124
--- src/interfaces/libpq/fe-exec.c 2003/01/13 11:59:36
***************
*** 12,20 ****
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
- #include <errno.h>
#include <ctype.h>
#include <fcntl.h>
--- 12,21 ----
*
*-------------------------------------------------------------------------
*/
+
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#include <ctype.h>
#include <fcntl.h>
Index: src/interfaces/libpq/fe-lobj.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-lobj.c,v
retrieving revision 1.41
diff -c -r1.41 fe-lobj.c
*** src/interfaces/libpq/fe-lobj.c 2002/06/20 20:29:54 1.41
--- src/interfaces/libpq/fe-lobj.c 2003/01/13 11:59:36
***************
*** 12,17 ****
--- 12,19 ----
*
*-------------------------------------------------------------------------
*/
+
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#include <fcntl.h>
***************
*** 396,404 ****
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
return InvalidOid;
}
--- 398,407 ----
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
return InvalidOid;
}
***************
*** 479,487 ****
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
(void) lo_close(conn, lobj);
return -1;
}
--- 482,491 ----
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
(void) lo_close(conn, lobj);
return -1;
}
Index: src/interfaces/libpq/fe-misc.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-misc.c,v
retrieving revision 1.86
diff -c -r1.86 fe-misc.c
*** src/interfaces/libpq/fe-misc.c 2003/01/07 22:23:17 1.86
--- src/interfaces/libpq/fe-misc.c 2003/01/13 11:59:36
***************
*** 30,35 ****
--- 30,36 ----
*-------------------------------------------------------------------------
*/
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#include <errno.h>
***************
*** 381,393 ****
if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
&timeout) < 0)
{
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry1;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 382,395 ----
if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
&timeout) < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry1;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 415,427 ****
if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
&timeout) < 0)
{
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry2;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
--- 417,430 ----
if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
&timeout) < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
/* Interrupted system call - we'll just try again */
goto retry2;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
***************
*** 443,448 ****
--- 446,452 ----
{
int someread = 0;
int nread;
+ char sebuf[256];
if (conn->sock < 0)
{
***************
*** 513,519 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 517,523 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 593,599 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 597,603 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 654,659 ****
--- 658,664 ----
while (len > 0)
{
int sent;
+ char sebuf[256];
sent = pqsecure_write(conn, ptr, len);
***************
*** 700,706 ****
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
/* We don't assume it's a fatal error... */
return -1;
}
--- 705,711 ----
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
/* We don't assume it's a fatal error... */
return -1;
}
***************
*** 850,860 ****
&except_mask, ptmp_timeout);
if (selresult < 0)
{
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return EOF;
}
if (selresult == 0)
--- 855,866 ----
&except_mask, ptmp_timeout);
if (selresult < 0)
{
+ char sebuf[256];
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return EOF;
}
if (selresult == 0)
Index: src/interfaces/libpq/fe-print.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-print.c,v
retrieving revision 1.47
diff -c -r1.47 fe-print.c
*** src/interfaces/libpq/fe-print.c 2002/10/03 17:09:42 1.47
--- src/interfaces/libpq/fe-print.c 2003/01/13 11:59:36
***************
*** 14,19 ****
--- 14,21 ----
*
*-------------------------------------------------------------------------
*/
+
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#include <signal.h>
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.20
diff -c -r1.20 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 2003/01/08 23:18:25 1.20
--- src/interfaces/libpq/fe-secure.c 2003/01/13 11:59:36
***************
*** 79,84 ****
--- 79,85 ----
*-------------------------------------------------------------------------
*/
+ #include "libpq-reentrant.h"
#include "postgres_fe.h"
#include <sys/types.h>
***************
*** 272,280 ****
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
--- 273,284 ----
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! {
! char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! }
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
***************
*** 319,327 ****
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
--- 323,334 ----
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
! {
! char sebuf[256];
! printfPQExpBuffer(&conn->errorMessage,
! libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! }
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
***************
*** 385,393 ****
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 392,401 ----
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 465,478 ****
static DH *
load_dh_file(int keylength)
{
! struct passwd *pwd;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if ((pwd = getpwuid(getuid())) == NULL)
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
--- 473,488 ----
static DH *
load_dh_file(int keylength)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
***************
*** 605,619 ****
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! struct passwd *pwd;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
! if ((pwd = getpwuid(getuid())) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
--- 615,633 ----
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
+ char sebuf[256];
+
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
***************
*** 629,635 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
--- 643,649 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
***************
*** 665,671 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, strerror(errno));
X509_free(*x509);
return -1;
}
--- 679,685 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
X509_free(*x509);
return -1;
}
***************
*** 709,715 ****
initialize_SSL(PGconn *conn)
{
struct stat buf;
! struct passwd *pwd;
char fnbuf[2048];
if (!SSL_context)
--- 723,731 ----
initialize_SSL(PGconn *conn)
{
struct stat buf;
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
char fnbuf[2048];
if (!SSL_context)
***************
*** 726,732 ****
}
}
! if ((pwd = getpwuid(getuid())) != NULL)
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
--- 742,748 ----
}
}
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
***************
*** 734,743 ****
{
return 0;
#ifdef NOT_USED
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
#endif
}
--- 750,760 ----
{
return 0;
#ifdef NOT_USED
+ char sebuf[256];
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
return -1;
#endif
}
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.60
diff -c -r1.60 libpq-int.h
*** src/interfaces/libpq/libpq-int.h 2002/10/16 02:55:30 1.60
--- src/interfaces/libpq/libpq-int.h 2003/01/13 11:59:36
***************
*** 26,31 ****
--- 26,32 ----
#include <sys/time.h>
#endif
+
#if defined(WIN32) && (!defined(ssize_t))
typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast
* not VC6) */
***************
*** 389,395 ****
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR strerror
#endif
#endif /* LIBPQ_INT_H */
--- 390,396 ----
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR pqStrerror
#endif
#endif /* LIBPQ_INT_H */
Index: src/interfaces/libpq/win32.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/win32.c,v
retrieving revision 1.4
diff -c -r1.4 win32.c
*** src/interfaces/libpq/win32.c 2002/09/04 20:31:47 1.4
--- src/interfaces/libpq/win32.c 2003/01/13 11:59:36
***************
*** 271,283 ****
*/
const char *
! winsock_strerror(int err)
{
- static char buf[512]; /* Not threadsafe */
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, buf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
--- 271,282 ----
*/
const char *
! winsock_strerror(int err, char *strerrbuf, size_t buflen)
{
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, strerrbuf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
***************
*** 302,321 ****
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! buf, sizeof(buf) - 64,
0
);
}
if (!success)
! sprintf(buf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! buf[sizeof(buf) - 1] = '\0';
! offs = strlen(buf);
! if (offs > sizeof(buf) - 64)
! offs = sizeof(buf) - 64;
! sprintf(buf + offs, " (0x%08X/%lu)", err, err);
}
! return buf;
}
--- 301,320 ----
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! strerrbuf, buflen - 64,
0
);
}
if (!success)
! sprintf(strerrbuf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! strerrbuf[buflen - 1] = '\0';
! offs = strlen(strerrbuf);
! if (offs > buflen - 64)
! offs = buflen - 64;
! sprintf(strerrbuf + offs, " (0x%08X/%lu)", err, err);
}
! return strerrbuf;
}
Index: src/interfaces/libpq/win32.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/win32.h,v
retrieving revision 1.21
diff -c -r1.21 win32.h
*** src/interfaces/libpq/win32.h 2002/12/30 21:07:26 1.21
--- src/interfaces/libpq/win32.h 2003/01/13 11:59:36
***************
*** 42,48 ****
/*
* support for handling Windows Socket errors
*/
! extern const char *winsock_strerror(int eno);
!
#endif
--- 42,47 ----
/*
* support for handling Windows Socket errors
*/
! extern const char *winsock_strerror(int err, char *strerrbuf, size_t buflen);
#endif
Your patch has been added to the PostgreSQL unapplied patches list at:
http://momjian.postgresql.org/cgi-bin/pgpatches
I will try to apply it within the next 48 hours.
---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body text
Patch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Lee, I have a question about this code:
char *pqStrerror(int errnum, char *strerrbuf, size_t buflen)
{
#if defined HAVE_STRERROR_R
/* reentrant strerror_r is available */
strerror_r(errnum, strerrbuf, buflen);
return strerrbuf;
#elif defined HAVE_NONPOSIX_STRERROR_R
/* broken (well early POSIX draft) strerror_r() which returns 'char *' */
return strerror_r(errnum, strerrbuf, buflen);
#else
/* no strerror_r() available, just use strerror */
return strerror(errnum);
#endif
}
Why do we have to care about HAVE_NONPOSIX_STRERROR_R? Can't we just
use the HAVE_STRERROR_R code in all cases?
---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body text
Patch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Your call, but the "broken" call is in earlier glibc versions for
sure (if you're on a Linux box take a look in /usr/include - the
prototype is still there, may even get used depending on compiler
options!). I seem to remember compiling this on recent Solaris, HPUX,
Linux and AIX versions without hitting the "broken" version, but...
L.
Bruce Momjian writes:
Show quoted text
Lee, I have a question about this code:
char *pqStrerror(int errnum, char *strerrbuf, size_t buflen)
{
#if defined HAVE_STRERROR_R
/* reentrant strerror_r is available */
strerror_r(errnum, strerrbuf, buflen);
return strerrbuf;
#elif defined HAVE_NONPOSIX_STRERROR_R
/* broken (well early POSIX draft) strerror_r() which returns 'char *' */
return strerror_r(errnum, strerrbuf, buflen);
#else
/* no strerror_r() available, just use strerror */
return strerror(errnum);
#endif
}Why do we have to care about HAVE_NONPOSIX_STRERROR_R? Can't we just
use the HAVE_STRERROR_R code in all cases?---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body textPatch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
-- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
My point is why do we care whether it returns char * or nothing --- we
should just return strerrbuf in all cases.
---------------------------------------------------------------------------
Lee Kindness wrote:
Your call, but the "broken" call is in earlier glibc versions for
sure (if you're on a Linux box take a look in /usr/include - the
prototype is still there, may even get used depending on compiler
options!). I seem to remember compiling this on recent Solaris, HPUX,
Linux and AIX versions without hitting the "broken" version, but...L.
Bruce Momjian writes:
Lee, I have a question about this code:
char *pqStrerror(int errnum, char *strerrbuf, size_t buflen)
{
#if defined HAVE_STRERROR_R
/* reentrant strerror_r is available */
strerror_r(errnum, strerrbuf, buflen);
return strerrbuf;
#elif defined HAVE_NONPOSIX_STRERROR_R
/* broken (well early POSIX draft) strerror_r() which returns 'char *' */
return strerror_r(errnum, strerrbuf, buflen);
#else
/* no strerror_r() available, just use strerror */
return strerror(errnum);
#endif
}Why do we have to care about HAVE_NONPOSIX_STRERROR_R? Can't we just
use the HAVE_STRERROR_R code in all cases?---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body textPatch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
-- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Bruce Momjian writes:
My point is why do we care whether it returns char * or nothing --- we
should just return strerrbuf in all cases.
Ok, I see. Guess that is reasonable.
L.
Lee, I have been looking at the code, and though the quoted function is
OK to avoid the non-posix case, it seems the later ones are a problem:
#if defined HAVE_NONPOSIX_GETPWUID_R
/* broken (well early POSIX draft) getpwuid_r() which returns
* 'struct passwd *' */
*result = getpwuid_r(uid, resultbuf, buffer, buflen);
#else
/* no getpwuid_r() available, just use getpwuid() */
*result = getpwuid(uid);
#endif /* HAVE_NONPOSIX_GETPWUID_R */
return( (*result == NULL) ? -1 : 0 );
In this case, what logic do we use? Seems you don't want to use
getpwuid_r if it exists, but only if getpwuid isn't thread safe, and I
have no idea how do to this. Can we just use the *_r versions if they
exist?
---------------------------------------------------------------------------
Bruce Momjian wrote:
Lee, I have a question about this code:
char *pqStrerror(int errnum, char *strerrbuf, size_t buflen)
{
#if defined HAVE_STRERROR_R
/* reentrant strerror_r is available */
strerror_r(errnum, strerrbuf, buflen);
return strerrbuf;
#elif defined HAVE_NONPOSIX_STRERROR_R
/* broken (well early POSIX draft) strerror_r() which returns 'char *' */
return strerror_r(errnum, strerrbuf, buflen);
#else
/* no strerror_r() available, just use strerror */
return strerror(errnum);
#endif
}Why do we have to care about HAVE_NONPOSIX_STRERROR_R? Can't we just
use the HAVE_STRERROR_R code in all cases?---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body textPatch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
-- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
I see these in the patch:
/* Setup _THREAD_SAFE and _POSIX_PTHREAD_SEMANTICS, this will disappear
* in time once tests to determine correct compiler switches for threads
* are added to configure.
*/
#if !defined _THREAD_SAFE
#define _THREAD_SAFE
#endif
#if !defined _POSIX_PTHREAD_SEMANTICS
#define _POSIX_PTHREAD_SEMANTICS
#endif
What platforms use these? Linux? I don't see them on BSD/OS.
---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body text
Patch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Here is the final patch for libpq threading. It adds the bulk of your
patch, plus some cleanups on calling reentrant functions.
We now have these per-platform configure settings:
linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
THREAD_LIBS="-lpthread"
NEED_REENTRANT_FUNC_NAMES=yes
They control compile flags, link libraries, and the use of reentrant
function names.
---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body text
Patch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Attachments:
/bjm/difftext/plainDownload
Index: configure
===================================================================
RCS file: /cvsroot/pgsql-server/configure,v
retrieving revision 1.271
diff -c -c -r1.271 configure
*** configure 14 Jun 2003 14:35:42 -0000 1.271
--- configure 14 Jun 2003 17:12:15 -0000
***************
*** 3591,3596 ****
--- 3591,3600 ----
#
# Pthreads
#
+ # For each platform, we need to know about any special compile and link
+ # libraries, and whether the normal C function names are thread-safe.
+ #
+ NEED_REENTRANT_FUNC_NAMES=no
if test "$with_threads" = yes; then
echo "$as_me:$LINENO: checking for ANSI C header files" >&5
echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
***************
*** 3902,3914 ****
case $host_os in
netbsd*|bsdi*)
# these require no special flags or libraries
;;
- freebsd2*|freebsd3*|freebsd4*) THREAD_CFLAGS="-pthread" ;;
freebsd*)
THREAD_LIBS="-lc_r"
;;
linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
THREAD_LIBS="-lpthread"
;;
*)
# other operating systems might fail because they have pthread.h but need
--- 3906,3924 ----
case $host_os in
netbsd*|bsdi*)
# these require no special flags or libraries
+ NEED_REENTRANT_FUNC_NAMES=no
+ ;;
+ freebsd2*|freebsd3*|freebsd4*)
+ THREAD_CFLAGS="-pthread"
+ NEED_REENTRANT_FUNC_NAMES=yes
;;
freebsd*)
THREAD_LIBS="-lc_r"
+ NEED_REENTRANT_FUNC_NAMES=yes
;;
linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
THREAD_LIBS="-lpthread"
+ NEED_REENTRANT_FUNC_NAMES=yes
;;
*)
# other operating systems might fail because they have pthread.h but need
***************
*** 12829,12836 ****
#
# Check for re-entrant versions of certain functions
#
! # Include special flags if required
#
_CFLAGS="$CFLAGS"
_LIB="$LIBS"
CFLAGS="$CFLAGS $TREAD_CFLAGS"
--- 12839,12852 ----
#
# Check for re-entrant versions of certain functions
#
! # Include special flags if threads are enabled _and_ if required for
! # threading on this platform. Some platforms have *_r functions but
! # their natively named funcs are threadsafe, and should be used instead.
! #
! # One trick here is that if the don't call AC_CHECK_FUNCS, the
! # functions are marked "not found", which is perfect.
#
+ if test "$NEED_REENTRANT_FUNC_NAMES" = yes ; then
_CFLAGS="$CFLAGS"
_LIB="$LIBS"
CFLAGS="$CFLAGS $TREAD_CFLAGS"
***************
*** 12915,12921 ****
CFLAGS="$_CFLAGS"
LIB="$_LIBS"
!
# This test makes sure that run tests work at all. Sometimes a shared
--- 12931,12937 ----
CFLAGS="$_CFLAGS"
LIB="$_LIBS"
! fi
# This test makes sure that run tests work at all. Sometimes a shared
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql-server/configure.in,v
retrieving revision 1.262
diff -c -c -r1.262 configure.in
*** configure.in 14 Jun 2003 14:35:42 -0000 1.262
--- configure.in 14 Jun 2003 17:12:16 -0000
***************
*** 554,571 ****
#
# Pthreads
#
if test "$with_threads" = yes; then
AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([pthread.h not found, required for --with-threads])])
case $host_os in
! netbsd*|bsdi*)
# these require no special flags or libraries
;;
- freebsd2*|freebsd3*|freebsd4*) THREAD_CFLAGS="-pthread" ;;
freebsd*)
THREAD_LIBS="-lc_r"
;;
linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
THREAD_LIBS="-lpthread"
;;
*)
# other operating systems might fail because they have pthread.h but need
--- 554,581 ----
#
# Pthreads
#
+ # For each platform, we need to know about any special compile and link
+ # libraries, and whether the normal C function names are thread-safe.
+ #
+ NEED_REENTRANT_FUNC_NAMES=no
if test "$with_threads" = yes; then
AC_CHECK_HEADER(pthread.h, [], [AC_MSG_ERROR([pthread.h not found, required for --with-threads])])
case $host_os in
! netbsd*|bsdi*)
# these require no special flags or libraries
+ NEED_REENTRANT_FUNC_NAMES=no
+ ;;
+ freebsd2*|freebsd3*|freebsd4*)
+ THREAD_CFLAGS="-pthread"
+ NEED_REENTRANT_FUNC_NAMES=yes
;;
freebsd*)
THREAD_LIBS="-lc_r"
+ NEED_REENTRANT_FUNC_NAMES=yes
;;
linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
THREAD_LIBS="-lpthread"
+ NEED_REENTRANT_FUNC_NAMES=yes
;;
*)
# other operating systems might fail because they have pthread.h but need
***************
*** 991,998 ****
#
# Check for re-entrant versions of certain functions
#
! # Include special flags if required
#
_CFLAGS="$CFLAGS"
_LIB="$LIBS"
CFLAGS="$CFLAGS $TREAD_CFLAGS"
--- 1001,1014 ----
#
# Check for re-entrant versions of certain functions
#
! # Include special flags if threads are enabled _and_ if required for
! # threading on this platform. Some platforms have *_r functions but
! # their natively named funcs are threadsafe, and should be used instead.
! #
! # One trick here is that if the don't call AC_CHECK_FUNCS, the
! # functions are marked "not found", which is perfect.
#
+ if test "$NEED_REENTRANT_FUNC_NAMES" = yes ; then
_CFLAGS="$CFLAGS"
_LIB="$LIBS"
CFLAGS="$CFLAGS $TREAD_CFLAGS"
***************
*** 1000,1006 ****
AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r])
CFLAGS="$_CFLAGS"
LIB="$_LIBS"
!
# This test makes sure that run tests work at all. Sometimes a shared
--- 1016,1022 ----
AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r])
CFLAGS="$_CFLAGS"
LIB="$_LIBS"
! fi
# This test makes sure that run tests work at all. Sometimes a shared
Index: src/interfaces/libpq/fe-auth.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-auth.c,v
retrieving revision 1.79
diff -c -c -r1.79 fe-auth.c
*** src/interfaces/libpq/fe-auth.c 8 Jun 2003 17:43:00 -0000 1.79
--- src/interfaces/libpq/fe-auth.c 14 Jun 2003 17:12:20 -0000
***************
*** 391,398 ****
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), strerror(errno));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
--- 391,400 ----
flags = fcntl(sock, F_GETFL);
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! libpq_gettext("could not set socket to blocking mode: %s\n"), pqStrerror(errno, sebuf, sizeof(sebuf)));
krb5_free_principal(pg_krb5_context, server);
return STATUS_ERROR;
}
***************
*** 436,444 ****
if (fcntl(sock, F_SETFL, (long) flags))
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! strerror(errno));
ret = STATUS_ERROR;
}
--- 438,448 ----
if (fcntl(sock, F_SETFL, (long) flags))
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
libpq_gettext("could not restore non-blocking mode on socket: %s\n"),
! pqStrerror(errno, sebuf, sizeof(sebuf)));
ret = STATUS_ERROR;
}
***************
*** 495,502 ****
if (sendmsg(conn->sock, &msg, 0) == -1)
{
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n", strerror(errno));
return STATUS_ERROR;
}
return STATUS_OK;
--- 499,509 ----
if (sendmsg(conn->sock, &msg, 0) == -1)
{
+ char sebuf[256];
+
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
! "pg_local_sendauth: sendmsg: %s\n",
! pqStrerror(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
***************
*** 739,748 ****
if (GetUserName(username, &namesize))
name = username;
#else
! struct passwd *pw = getpwuid(geteuid());
!
! if (pw)
! name = pw->pw_name;
#endif
}
--- 746,758 ----
if (GetUserName(username, &namesize))
name = username;
#else
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pw = NULL;
!
! if( pqGetpwuid(geteuid(), &pwdstr,
! pwdbuf, sizeof(pwdbuf), &pw) == 0 )
! name = pw->pw_name;
#endif
}
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.247
diff -c -c -r1.247 fe-connect.c
*** src/interfaces/libpq/fe-connect.c 12 Jun 2003 08:15:29 -0000 1.247
--- src/interfaces/libpq/fe-connect.c 14 Jun 2003 17:12:23 -0000
***************
*** 713,721 ****
{
if (FCNTL_NONBLOCK(conn->sock) < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
--- 713,723 ----
{
if (FCNTL_NONBLOCK(conn->sock) < 0)
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
***************
*** 738,746 ****
(char *) &on,
sizeof(on)) < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return 0;
}
#endif
--- 740,750 ----
(char *) &on,
sizeof(on)) < 0)
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return 0;
}
#endif
***************
*** 759,764 ****
--- 763,769 ----
{
char hostname[NI_MAXHOST];
char service[NI_MAXHOST];
+ char sebuf[256];
getnameinfo((struct sockaddr *)&conn->raddr.addr, conn->raddr.salen,
hostname, sizeof(hostname), service, sizeof(service),
***************
*** 770,776 ****
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno), service);
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
--- 775,781 ----
"\tIs the server running locally and accepting\n"
"\tconnections on Unix domain socket \"%s\"?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)), service);
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext(
***************
*** 778,784 ****
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno),
conn->pghostaddr
? conn->pghostaddr
: (conn->pghost
--- 783,789 ----
"\tIs the server running on host %s and accepting\n"
"\tTCP/IP connections on port %s?\n"
),
! SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
conn->pghostaddr
? conn->pghostaddr
: (conn->pghost
***************
*** 1001,1006 ****
--- 1006,1012 ----
PQconnectPoll(PGconn *conn)
{
PGresult *res;
+ char sebuf[256];
if (conn == NULL)
return PGRES_POLLING_FAILED;
***************
*** 1094,1100 ****
}
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
break;
}
--- 1100,1106 ----
}
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
break;
}
***************
*** 1200,1206 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
else if (optval != 0)
--- 1206,1212 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get socket error status: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
else if (optval != 0)
***************
*** 1237,1243 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
--- 1243,1249 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get client address from socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
***************
*** 1282,1288 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
/* Ok, wait for response */
--- 1288,1294 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
/* Ok, wait for response */
***************
*** 1317,1323 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
free(startpacket);
goto error_return;
}
--- 1323,1329 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send startup packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
free(startpacket);
goto error_return;
}
***************
*** 1357,1363 ****
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
goto error_return;
}
if (nread == 0)
--- 1363,1369 ----
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
goto error_return;
}
if (nread == 0)
***************
*** 2037,2042 ****
--- 2043,2049 ----
{
int save_errno = SOCK_ERRNO;
int tmpsock = -1;
+ char sebuf[256];
struct
{
uint32 packetlen;
***************
*** 2115,2121 ****
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
--- 2122,2128 ----
return TRUE;
cancel_errReturn:
! strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
strcat(conn->errorMessage.data, "\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
if (tmpsock >= 0)
***************
*** 2262,2269 ****
*val;
int found_keyword;
! key = strtok(line, "=");
! if (key == NULL)
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
--- 2269,2277 ----
*val;
int found_keyword;
! key = line;
! val = strchr(line, '=');
! if( val == NULL )
{
printfPQExpBuffer(errorMessage,
"ERROR: syntax error in service file '%s', line %d\n",
***************
*** 2272,2277 ****
--- 2280,2286 ----
fclose(f);
return 3;
}
+ *val++ = '\0';
/*
* If not already set, set the database name to the
***************
*** 2286,2293 ****
break;
}
}
-
- val = line + strlen(line) + 1;
/*
* Set the parameter --- but don't override any
--- 2295,2300 ----
Index: src/interfaces/libpq/fe-lobj.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-lobj.c,v
retrieving revision 1.41
diff -c -c -r1.41 fe-lobj.c
*** src/interfaces/libpq/fe-lobj.c 20 Jun 2002 20:29:54 -0000 1.41
--- src/interfaces/libpq/fe-lobj.c 14 Jun 2003 17:12:23 -0000
***************
*** 396,404 ****
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
return InvalidOid;
}
--- 396,405 ----
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
return InvalidOid;
}
***************
*** 479,487 ****
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, strerror(errno));
(void) lo_close(conn, lobj);
return -1;
}
--- 480,489 ----
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
! filename, pqStrerror(errno, sebuf, sizeof(sebuf)));
(void) lo_close(conn, lobj);
return -1;
}
Index: src/interfaces/libpq/fe-misc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-misc.c,v
retrieving revision 1.95
diff -c -c -r1.95 fe-misc.c
*** src/interfaces/libpq/fe-misc.c 12 Jun 2003 08:15:29 -0000 1.95
--- src/interfaces/libpq/fe-misc.c 14 Jun 2003 17:12:24 -0000
***************
*** 536,541 ****
--- 536,542 ----
{
int someread = 0;
int nread;
+ char sebuf[256];
if (conn->sock < 0)
{
***************
*** 606,612 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 607,613 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 686,692 ****
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
if (nread > 0)
--- 687,693 ----
#endif
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
if (nread > 0)
***************
*** 740,745 ****
--- 741,747 ----
while (len > 0)
{
int sent;
+ char sebuf[256];
sent = pqsecure_write(conn, ptr, len);
***************
*** 787,793 ****
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
/* We don't assume it's a fatal error... */
conn->outCount = 0;
return -1;
--- 789,795 ----
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
/* We don't assume it's a fatal error... */
conn->outCount = 0;
return -1;
***************
*** 963,971 ****
if (result < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
}
return result;
--- 965,975 ----
if (result < 0)
{
+ char sebuf[256];
+
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
}
return result;
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.23
diff -c -c -r1.23 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 8 Jun 2003 17:43:00 -0000 1.23
--- src/interfaces/libpq/fe-secure.c 14 Jun 2003 17:12:26 -0000
***************
*** 298,311 ****
*/
goto rloop;
case SSL_ERROR_SYSCALL:
if (n == -1)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
--- 298,316 ----
*/
goto rloop;
case SSL_ERROR_SYSCALL:
+ {
+ char sebuf[256];
+
if (n == -1)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
+
break;
+ }
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
***************
*** 360,373 ****
n = 0;
break;
case SSL_ERROR_SYSCALL:
if (n == -1)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
break;
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
--- 365,382 ----
n = 0;
break;
case SSL_ERROR_SYSCALL:
+ {
+ char sebuf[256];
+
if (n == -1)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
break;
+ }
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
***************
*** 434,442 ****
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
return -1;
}
--- 443,452 ----
len = sizeof(addr);
if (getpeername(conn->sock, &addr, &len) == -1)
{
+ char sebuf[256];
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("error querying socket: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
return -1;
}
***************
*** 514,527 ****
static DH *
load_dh_file(int keylength)
{
! struct passwd *pwd;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if ((pwd = getpwuid(getuid())) == NULL)
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
--- 524,539 ----
static DH *
load_dh_file(int keylength)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
FILE *fp;
char fnbuf[2048];
DH *dh = NULL;
int codes;
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
! return NULL;
/* attempt to open file. It's not an error if it doesn't exist. */
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/dh%d.pem",
***************
*** 654,668 ****
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! struct passwd *pwd;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
! if ((pwd = getpwuid(getuid())) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
--- 666,684 ----
static int
client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
struct stat buf,
buf2;
char fnbuf[2048];
FILE *fp;
PGconn *conn = (PGconn *) SSL_get_app_data(ssl);
int (*cb) () = NULL; /* how to read user password */
+ char sebuf[256];
+
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get user information\n"));
***************
*** 678,684 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
--- 694,700 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate (%s): %s\n"),
! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
return -1;
}
if (PEM_read_X509(fp, x509, NULL, NULL) == NULL)
***************
*** 714,720 ****
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, strerror(errno));
X509_free(*x509);
return -1;
}
--- 730,736 ----
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open private key file (%s): %s\n"),
! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
X509_free(*x509);
return -1;
}
***************
*** 758,764 ****
initialize_SSL(PGconn *conn)
{
struct stat buf;
! struct passwd *pwd;
char fnbuf[2048];
if (!SSL_context)
--- 774,782 ----
initialize_SSL(PGconn *conn)
{
struct stat buf;
! char pwdbuf[BUFSIZ];
! struct passwd pwdstr;
! struct passwd *pwd = NULL;
char fnbuf[2048];
if (!SSL_context)
***************
*** 775,781 ****
}
}
! if ((pwd = getpwuid(getuid())) != NULL)
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
--- 793,799 ----
}
}
! if( pqGetpwuid(getuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) == 0 )
{
snprintf(fnbuf, sizeof fnbuf, "%s/.postgresql/root.crt",
pwd->pw_dir);
***************
*** 783,792 ****
{
return 0;
#ifdef NOT_USED
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, strerror(errno));
return -1;
#endif
}
--- 801,811 ----
{
return 0;
#ifdef NOT_USED
+ char sebuf[256];
/* CLIENT CERTIFICATES NOT REQUIRED bjm 2002-09-26 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate list (%s): %s\n"),
! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf)));
return -1;
#endif
}
***************
*** 846,861 ****
return PGRES_POLLING_WRITING;
case SSL_ERROR_SYSCALL:
if (r == -1)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
close_SSL(conn);
return PGRES_POLLING_FAILED;
!
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
--- 865,883 ----
return PGRES_POLLING_WRITING;
case SSL_ERROR_SYSCALL:
+ {
+ char sebuf[256];
+
if (r == -1)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
! SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
close_SSL(conn);
return PGRES_POLLING_FAILED;
! }
case SSL_ERROR_SSL:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), SSLerrmessage());
Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.73
diff -c -c -r1.73 libpq-int.h
*** src/interfaces/libpq/libpq-int.h 12 Jun 2003 07:36:51 -0000 1.73
--- src/interfaces/libpq/libpq-int.h 14 Jun 2003 17:12:27 -0000
***************
*** 26,31 ****
--- 26,32 ----
#include <sys/time.h>
#endif
+
#if defined(WIN32) && (!defined(ssize_t))
typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast
* not VC6) */
***************
*** 448,454 ****
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR strerror
#endif
#endif /* LIBPQ_INT_H */
--- 449,455 ----
#define SOCK_STRERROR winsock_strerror
#else
#define SOCK_ERRNO errno
! #define SOCK_STRERROR pqStrerror
#endif
#endif /* LIBPQ_INT_H */
Index: src/interfaces/libpq/win32.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/win32.c,v
retrieving revision 1.4
diff -c -c -r1.4 win32.c
*** src/interfaces/libpq/win32.c 4 Sep 2002 20:31:47 -0000 1.4
--- src/interfaces/libpq/win32.c 14 Jun 2003 17:12:27 -0000
***************
*** 271,283 ****
*/
const char *
! winsock_strerror(int err)
{
- static char buf[512]; /* Not threadsafe */
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, buf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
--- 271,282 ----
*/
const char *
! winsock_strerror(int err, char *strerrbuf, size_t buflen)
{
unsigned long flags;
int offs,
i;
! int success = LookupWSErrorMessage(err, strerrbuf);
for (i = 0; !success && i < DLLS_SIZE; i++)
{
***************
*** 302,321 ****
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! buf, sizeof(buf) - 64,
0
);
}
if (!success)
! sprintf(buf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! buf[sizeof(buf) - 1] = '\0';
! offs = strlen(buf);
! if (offs > sizeof(buf) - 64)
! offs = sizeof(buf) - 64;
! sprintf(buf + offs, " (0x%08X/%lu)", err, err);
}
! return buf;
}
--- 301,320 ----
flags,
dlls[i].handle, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
! strerrbuf, buflen - 64,
0
);
}
if (!success)
! sprintf(strerrbuf, "Unknown socket error (0x%08X/%lu)", err, err);
else
{
! strerrbuf[buflen - 1] = '\0';
! offs = strlen(strerrbuf);
! if (offs > buflen - 64)
! offs = buflen - 64;
! sprintf(strerrbuf + offs, " (0x%08X/%lu)", err, err);
}
! return strerrbuf;
}
Index: src/interfaces/libpq/win32.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/win32.h,v
retrieving revision 1.22
diff -c -c -r1.22 win32.h
*** src/interfaces/libpq/win32.h 9 May 2003 16:59:43 -0000 1.22
--- src/interfaces/libpq/win32.h 14 Jun 2003 17:12:27 -0000
***************
*** 37,43 ****
/*
* support for handling Windows Socket errors
*/
! extern const char *winsock_strerror(int eno);
!
#endif
--- 37,42 ----
/*
* support for handling Windows Socket errors
*/
! extern const char *winsock_strerror(int err, char *strerrbuf, size_t buflen);
#endif
This patch handles two more gethostbyname calls.
---------------------------------------------------------------------------
Lee Kindness wrote:
Content-Description: message body text
Patch attached, along with new libpq-reentrant.c and libpq-reentrant.h
files for src/interfaces/libpq.Also at http://services.csl.co.uk/postgresql/
Thanks, Lee.
Lee Kindness writes:
Ok guys, I propose that the new libpq diff and 2 source files which
i'll soon send to pgsql-patches is applied to the source. This diff is
a cleaned up version of the previous version with the wrapper
functions moved out into their own file and more comments added. Also
the use of crypt_r() has been removed (not worth the effort), the
cpp defines have been renamed to be consistent with each other and
Tom's concerns with loose #defines has been partly addressed.This diff does not include any configure changes. I plan to tackle
this separately ASAP, and hopefully produce something more acceptable.I will add checks for appropriate compiler thread flags (for compiling
libpq, and alow the removal of #defines in libpq-reentrant.h), and
link flags & libs (for a planned threaded libpq test program and
renentrant ecpg library). If a thread environment is found then check
for the reentrant functions will be done.Looking at various open source projects configure.in files there seems
to be little commonality in the thread test macros (telp gratefully
accepted!), I currently think that something like the approach used by
glib is most suitable (switch on OS).All sound acceptable?
Thanks, Lee.
Peter Eisentraut writes:
Lee Kindness writes:
Patches attached to make libpq thread-safe, now uses strerror_r(),
gethostbyname_r(), getpwuid_r() and crypt_r() where available. Where
strtok() was previously used strchr() is now used.AC_TRY_RUN tests are prohibited. Also, try to factor out some of these
huge tests into separate macros and put them into config/c-library.m4.
And it would be nice if there was some documentation about what was
checked for. If you just want to check whether gethostbyname_r() has 5 or
6 arguments you can do that in half the space.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Attachments:
/bjm/difftext/plainDownload
Index: src/interfaces/libpq/fe-secure.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
retrieving revision 1.24
diff -c -c -r1.24 fe-secure.c
*** src/interfaces/libpq/fe-secure.c 14 Jun 2003 17:49:54 -0000 1.24
--- src/interfaces/libpq/fe-secure.c 14 Jun 2003 18:08:54 -0000
***************
*** 453,460 ****
if (addr.sa_family == AF_UNIX)
return 0;
/* what do we know about the peer's common name? */
! if ((h = gethostbyname(conn->peer_cn)) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get information about host (%s): %s\n"),
--- 453,469 ----
if (addr.sa_family == AF_UNIX)
return 0;
+ {
+ struct hostent hpstr;
+ char buf[BUFSIZ];
+ int herrno = 0;
+
+ pqGethostbyname(conn->peer_cn, &hpstr, buf, sizeof(buf),
+ &h, &herrno);
+ }
+
/* what do we know about the peer's common name? */
! if ((h == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get information about host (%s): %s\n"),
Index: src/port/getaddrinfo.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/getaddrinfo.c,v
retrieving revision 1.7
diff -c -c -r1.7 getaddrinfo.c
*** src/port/getaddrinfo.c 12 Jun 2003 08:15:29 -0000 1.7
--- src/port/getaddrinfo.c 14 Jun 2003 18:08:55 -0000
***************
*** 84,91 ****
--- 84,99 ----
else
{
struct hostent *hp;
+ #ifdef FRONTEND
+ struct hostent hpstr;
+ char buf[BUFSIZ];
+ int herrno = 0;
+ pqGethostbyname(node, &hpstr, buf, sizeof(buf),
+ &hp, &herrno);
+ #else
hp = gethostbyname(node);
+ #endif
if (hp == NULL)
{
switch (h_errno)
On Sat, Jun 14, 2003 at 02:20:44PM -0400, Bruce Momjian wrote:
This patch handles two more gethostbyname calls.
[...]
diff -c -c -r1.24 fe-secure.c *** src/interfaces/libpq/fe-secure.c 14 Jun 2003 17:49:54 -0000 1.24 --- src/interfaces/libpq/fe-secure.c 14 Jun 2003 18:08:54 -0000 *************** *** 453,460 **** if (addr.sa_family == AF_UNIX) return 0;/* what do we know about the peer's common name? */
! if ((h = gethostbyname(conn->peer_cn)) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get information about host (%s): %s\n"),
That code is inside #ifdef NOT_USED, which is why I didn't change
it in my ipv6 patch.
Should I convert that function to use getaddrinfo too?
Others I didn't change where pg_krb4_sendauth() and
pg_krb5_sendauth(), because I don't have a clue about kerberos.
Kurt
Kurt Roeckx wrote:
On Sat, Jun 14, 2003 at 02:20:44PM -0400, Bruce Momjian wrote:
This patch handles two more gethostbyname calls.
[...]
diff -c -c -r1.24 fe-secure.c *** src/interfaces/libpq/fe-secure.c 14 Jun 2003 17:49:54 -0000 1.24 --- src/interfaces/libpq/fe-secure.c 14 Jun 2003 18:08:54 -0000 *************** *** 453,460 **** if (addr.sa_family == AF_UNIX) return 0;/* what do we know about the peer's common name? */
! if ((h = gethostbyname(conn->peer_cn)) == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get information about host (%s): %s\n"),That code is inside #ifdef NOT_USED, which is why I didn't change
it in my ipv6 patch.
Yes, I noticed that, but it seemed reasonable to get things consistent.
Should I convert that function to use getaddrinfo too?
Others I didn't change where pg_krb4_sendauth() and
pg_krb5_sendauth(), because I don't have a clue about kerberos.
I understand. I guess we should be consisent if we can be.
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073