Am 16.04.2016 um 12:09 schrieb Ben RUBSON:
Ben: have a look at how mod_rewrite accesses its own
ap_register_rewrite_mapfunc via
So Rainer, I just quickly wrote my module, it works, many thanks for your help.
Below is my code, I just have 2 questions regarding it :
1 - do I need to "free(pw)" ?
Good question. My (Solaris) man page for getpwnam() says:
Reentrant Interfaces
The getpwnam(), getpwuid(), getpwent(), and fgetpwent()
functions use thread-specific data storage that is reused in
each call to one of these functions by the same thread, mak-
ing them safe to use but not recommeded for multithreaded
applications.
The Linux man page says:
The return value may point to a static area, and may be
overwritten by subsequent calls to getpwent(3), getpwnam(), or
getpwuid(). (Do not pass the
returned pointer to free(3).)
And the latest standards man page of the OpenGroup says:
The getpwnam() function need not be thread-safe.
...
The application shall not modify the structure to which the return value
points, nor any storage areas pointed to by pointers within the
structure. The returned pointer, and pointers within the structure,
might be invalidated or the structure or the storage areas might be
overwritten by a subsequent call to getpwent(), getpwnam(), or getpwuid().
So you must not free the returned pointer. Two of the man pages don't
guarantee thread safety so to stay on the safe side you probably better
use the reentrant variants getpwnam_r() and getpwuid_r(). For those you
need to allocate the storage before calling them. You can either
allocate storage from the request pool (apr_palloc(r->pool, N)) or using
malloc/free. Modules typically prefer pool allocation. Pool allocation
doesn't need to be freed. The request pool is automatically freed at the
end of each request. Even if you need the memory only shorter, if it is
not many bytes it should be OK to allocate from the request pool and let
it free only at the end of the request.
2 - is "key = apr_palloc(r->pool, 7)" the right method ? Doing this I want to
avoid buffer overflow in case of uid/gid greater in length than the key parameter.
Instead of
key = apr_palloc(r->pool, 7);
printf(key, "%d", pw->pw_uid);
you can also use
key = apr_psprintf(r->pool, "%d", pw->pw_uid);
And if you are not going to use more complex formatting tokens
key = apr_ltoa(r->pool, (long)pw->pw_uid);
There's also an apr_itoa() but we might not be sure, that uid_t fits
into an int.
Finally as a matter of style, I wouldn't reuse the incoming variable
"key" for outgoing tasks. Instead I would declare it "const char*" as a
param, and where you set
*key = '\0';
you could also
return "";
and then later
return apr_ltoa(r->pool, (long)pw->pw_uid);
Everything untested ...
But as always there are many solutions that will work.
Thank you very much,
You're welcome. Nice seeing you picking up that ball so quickly. Welcome
to the world of module development :) Your example was a nice one,
because you don't need much clutter to realize that module.
Regards,
Rainer
#include "http_core.h"
#include "mod_rewrite.h"
#include <pwd.h>
static char *uid(request_rec *r, char *key)
{
struct passwd *pw;
if((pw = getpwnam(key)) == NULL)
{
*key = '\0';
}
else
{
key = apr_palloc(r->pool, 7);
sprintf(key, "%d", pw->pw_uid);
}
return key;
}
static char *gid(request_rec *r, char *key)
{
int uid=atoi(key);
struct passwd *pw;
if((pw = getpwuid(uid)) == NULL)
{
*key = '\0';
}
else
{
key = apr_palloc(r->pool, 7);
sprintf(key, "%d", pw->pw_gid);
return key;
}
return key;
}
static void register_hooks(apr_pool_t *pool)
{
APR_OPTIONAL_FN_TYPE(ap_register_rewrite_mapfunc) *map_pfn_register;
map_pfn_register =
APR_RETRIEVE_OPTIONAL_FN(ap_register_rewrite_mapfunc);
map_pfn_register("uid", uid);
map_pfn_register("gid", gid);
}
AP_DECLARE_MODULE(test) = {
STANDARD20_MODULE_STUFF,NULL,NULL,NULL,NULL,NULL,register_hooks
};
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@httpd.apache.org
For additional commands, e-mail: users-h...@httpd.apache.org