#include "k5-int.h"
#include <stdarg.h>
krb5_error_code KRB5_CALLCONV_C
krb5_build_principal_ext(krb5_context context, krb5_principal * princ,
unsigned int rlen, const char * realm, ...)
{
va_list ap;
register int i, count = 0;
register unsigned int size;
register char *next;
char *tmpdata = 0;
krb5_data *princ_data;
krb5_principal princ_ret;
va_start(ap, realm);
while (va_arg(ap, int) != 0) {
(void)va_arg(ap, char *);
count++;
}
va_end(ap);
princ_data = (krb5_data *) malloc(sizeof(krb5_data) * count);
if (!princ_data)
return ENOMEM;
princ_ret = (krb5_principal) malloc(sizeof(krb5_principal_data));
if (!princ_ret) {
krb5_xfree(princ_data);
return ENOMEM;
}
princ_ret->data = princ_data;
princ_ret->length = count;
tmpdata = malloc(rlen+1);
if (!tmpdata) {
krb5_xfree(princ_data);
krb5_xfree(princ_ret);
return ENOMEM;
}
krb5_princ_set_realm_length(context, princ_ret, rlen);
krb5_princ_set_realm_data(context, princ_ret, tmpdata);
memcpy(tmpdata, realm, rlen);
tmpdata[rlen] = 0;
va_start(ap, realm);
for (i = 0; i < count; i++) {
size = va_arg(ap, unsigned int);
next = va_arg(ap, char *);
princ_data[i].length = size;
princ_data[i].data = malloc(size+1);
if (!princ_data[i].data)
goto free_out;
memcpy(princ_data[i].data, next, size);
princ_data[i].data[size] = 0;
}
va_end(ap);
*princ = princ_ret;
krb5_princ_type(context, princ_ret) = KRB5_NT_UNKNOWN;
return 0;
free_out:
while (--i >= 0)
krb5_xfree(princ_data[i].data);
krb5_xfree(princ_data);
krb5_xfree(princ_ret);
krb5_xfree(tmpdata);
va_end(ap);
return ENOMEM;
}