Am Die, 2002-11-19 um 15.17 schrieb Patrik Stridvall:
One thing that you shouldn't assume is for example that
if a function exists its reentrant variant exists as well.
Sure, got that.
And yes, you really should use the
reentrent variant if present as well as having an
alternative implementation if not.
Hmm - really really always? This generates messy code,
and a lot of effort for very rare cases.
Bad formulation. What I meant is that the code shouldn't
depend on the existance of the reentrant function since
it is not that unlikely that some platforms might only
have the non reentrent one only.
Still, I think we might need such a strict policy regardless.
I think we need a compromise, something in the line of either
- a) use non-reentrant functions, protecting them with a critical
section (IMO ok for rarely called functions) or
That is potentially slow since it uses locks.
Not that likely to be a problem with the getpw* functions
though but still...
- b) use only reentrant and treat the case where these aren't
available like the case where the respective functions aren't
available at all.
No, not a good solution. There are rational reasons to not have
the reentrent variants.
Of course b) would only be viable if a sufficiently large portion of
systems that support the non-reentrant variant support the
reentrant one
as well. I have no idea whether that's the case for the getpwXYZ
functions.
If are on a embedded platform it is not entirely unlikely that it
is possible to configure and compile the C library to not handle
reentrancy issues in order to optimize for space.
In fact it might make sense be able compile Winelib as not
supporting reentrency either. It is a post 1.0 issue IMHO,
but we should have a policy planning for that possiblity
nether the less.
So strictly speaking, we should IMHO do
#ifdef HAVE_GETPWUID_R
/* Use getpwuid_r */
#elsif defined(HAVE_GETPWUID)
# ifdef _REENTRANT
/* Lock. Use getpwuid. Unlock */
# else
/* Use getpwuid */
# endif
#else
/* Fail gracefully */
#endif
However adding the #ifdef _REENTRANT is a post 1.0 issue IMHO.
As to the implict existance question: I'm not sure.
First of all, to answer the related question:
Should you have a alternative implementation for
defined(HAVE_GETPWUID) && !defined(HAVE_GETPWNAM)?
IMHO the answer is no. It is not worth the effort to
support hypotetical platforms unless we can verify the
existance of one.
Very true. Perhaps the practical way would be to assume
HAVE_GETPWUID == HAVE_GETPWNAM and see whether someone with
a really strange platform complains (but see below).
Assume yes, however I think the should also verify as below.
I suggest that we should detect the presence or absence
of ALL function we use that is verified not to exist on
some platform and have for example code like
#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWNAM) ||
defined(HAVE_GETPWENT)
# if (defined(HAVE_GETPWUID) + defined(HAVE_GETPWNAM) +
defined(HAVE_GETPWENT)) == 3
# define __HAVE_GETPW
# else
# error All or none of the functions getpwuid, getpwnam
and getpwent are
assumed to exist
# endif
#endif
in order to formalize the assumptions and generate a common
define to use in
the code.
Well I'd say that for a start we could simply do something like
/* CAUTION: If there turns out to be some insane platform that has
- getpwuid() but not getpwnam() and getpwent(), this must be
- improved.
*/
#define __HAVE_GETPW HAVE_GETPWUID
This would keep bloat out of configure in the first place, while
providing a generic __HAVE_GETPW macro for possible later use.
As Alexandre said, having a special define is completely unnessary.
Just test for existance of whatever function when you call it.