I'm trying to build python-kerberos on AIX. kerberospw.c uses a call to asprintf, but from what Google is telling me, asprintf does not exist on AIX.
I saw http://www.koders.com/c/fidAA9B130D588302673A28B568430A83131B7734C0.aspx?s=windows.h, which looks like I could create a stand-in asprintf, but I don't know where this would go or how I would #include it in kerberospw.c.
Is there a way I can use the koders.com example or some other code to "fake" asprintf? Can I just include the asprintf function as shown in kerberospw.c? I am not a C coder, but
asprintf (char **resultp, const char *format, ...)
doesn't look like a valid signature to me with the dots at the end. The relevant line from kerberospw.c is below
asprintf(&message, "%.*s: %.*s", (int) result_code_string.length,
(char *) result_code_string.data,
(int) result_string.length,
(char *) result_string.data);
I realize I could contact the author of python-kerberos, but a) I think it would be helpful to have a potential patch if I did so, and b) there might be other software I run across that uses asprintf, and it would be nice to have a workaround.
Here an implementation that doesn't call snprintf()
twice in most of the cases. I omitted the includes and defines as shown in other responses.
As it should be, define the asprintf()
as a call to vasprintf()
int asprintf(char **dst, const char * pcFormat, ...)
{
va_list ap;
va_start(ap, pcFormat);
int len = vasprintf(dst, pcFormat, ap);
va_end(ap);
return len;
}
We preallocate a buffer to an predefined appropriate size and only in case of overflow call vsnprintf()
a second time. The rationale being that s*printf()
function are considered very heavy and overallocating memory being acceptable.
int vasprintf(char **dst, const char * pcFormat, va_list ap)
{
int len = 512; /* Worked quite well on our project */
int allocated = 0;
va_list ap_copy;
char *buff = NULL;
while(len >= allocated) {
free(buff);
buff = malloc(len+1);
if(buff) {
allocated = len+1;
va_copy(ap_copy, ap);
len = vsnprintf(buff, len+1, pcFormat, ap_copy);
va_end(ap_copy);
}
else /* malloc() failed */
return -1;
}
*dst = buff;
return len;
}
EDIT: I replaced the realloc()
call by a simple malloc()
as it is cheaper. In the case of overflow a free()/malloc()
pair costs less than realloc()
because of its internal hidden memcpy()
. As we overwrite the whole buffer anyway with the subsequent call to vsnprintf()
there is no point in that copy.
The asprintf
is a variation of the printf
family of function that allocate a buffer to hold the memory for the formatted string and return it. It is a function with a variable number of argument (hence the ...
in the declaration that is valid C code). You can find a description here.
It can be reimplemented relatively easily if the vsnprintf
is functioning correctly (ie, return an error if the buffer is too small to hold the formatted string).
Here is such an implementation:
#include <stdarg.h>
int asprintf(char **ret, const char *format, ...)
{
va_list ap;
*ret = NULL; /* Ensure value can be passed to free() */
va_start(ap, format);
int count = vsnprintf(NULL, 0, format, ap);
va_end(ap);
if (count >= 0)
{
char* buffer = malloc(count + 1);
if (buffer == NULL)
return -1;
va_start(ap, format);
count = vsnprintf(buffer, count + 1, format, ap);
va_end(ap);
if (count < 0)
{
free(buffer);
return count;
}
*ret = buffer;
}
return count;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With