#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mach/mach.h>
#include <servers/bootstrap.h>
#include <pthread.h>
#include <errno.h>
#include <notify.h>
#include <syslog.h>
#include <unistd.h>
#ifdef DEBUG
#include <asl.h>
#endif
#include <ils.h>
#define ILS_MAGIC_SIZE 8
#define ILS_MAGIC "ILSMAGIC"
static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 4 };
static const uint32_t align_64[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 };
static uint32_t
padsize(size_t curr, size_t item, const uint32_t *align)
{
uint32_t na, diff;
if (item > 8) item = 8;
na = align[item];
if (na == 0) return 0;
diff = curr % na;
if (diff == 0) return 0;
return na - diff;
}
void *
LI_ils_create(char *fmt, ...)
{
va_list ap;
char *arg, *f;
char **list;
void *hp, *dp, *lp, *ils;
uint8_t u8;
uint16_t u16;
uint32_t u32, i, pad;
uint64_t u64;
unsigned long l;
mach_port_t m;
socket_data_t sdata;
size_t memsize, hsize, csize, csizep1, csizep2, slen, largest;
const uint32_t *align;
if (fmt == NULL) return NULL;
largest = 0;
align = align_32;
if (sizeof(char *) == 8) align = align_64;
memsize = ILS_MAGIC_SIZE;
hsize = 0;
va_start(ap, fmt);
for (f = fmt; (*f) != '\0'; f++)
{
csize = 0;
slen = 0;
switch (*f)
{
case 's':
{
if (largest < sizeof(char *)) largest = sizeof(char *);
csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
arg = va_arg(ap, char *);
if (arg != NULL) slen = strlen(arg) + 1;
break;
}
case '1':
{
if (largest < 1) largest = 1;
csize = 1;
u8 = va_arg(ap, int);
break;
}
case '2':
{
if (largest < 2) largest = 2;
csize = 2 + padsize(hsize, 2, align);
u16 = va_arg(ap, int);
break;
}
case '4':
{
if (largest < 4) largest = 4;
csize = 4 + padsize(hsize, 4, align);
u32 = va_arg(ap, uint32_t);
break;
}
case '8':
{
if (largest < 8) largest = 8;
csize = 8 + padsize(hsize, 8, align);
u64 = va_arg(ap, uint64_t);
break;
}
case 'S':
{
if (largest < 128) largest = 128;
csize = 128 + padsize(hsize, 4, align);
sdata = va_arg(ap, socket_data_t);
break;
}
case 'L':
{
if (largest < sizeof(unsigned long)) largest = sizeof(unsigned long);
csize = sizeof(unsigned long) + padsize(hsize, sizeof(unsigned long), align);
l = va_arg(ap, unsigned long);
break;
}
case 'm':
{
if (largest < sizeof(mach_port_t)) largest = sizeof(mach_port_t);
csize = sizeof(mach_port_t) + padsize(hsize, sizeof(mach_port_t), align);
m = va_arg(ap, mach_port_t);
break;
}
case '*':
{
if (largest < sizeof(char *)) largest = sizeof(char *);
csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
list = va_arg(ap, char **);
if (list != NULL)
{
for (i = 0; list[i] != NULL; i++)
{
slen += sizeof(char *);
slen += (strlen(list[i]) + 1);
}
}
slen += sizeof(char *);
break;
}
case 'a':
{
if (largest < sizeof(char *)) largest = sizeof(char *);
csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
list = va_arg(ap, char **);
if (list != NULL)
{
for (i = 0; list[i] != NULL; i++)
{
slen += sizeof(char *);
slen += 4;
}
slen += sizeof(char *);
}
break;
}
case 'b':
{
if (largest < sizeof(char *)) largest = sizeof(char *);
csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
list = va_arg(ap, char **);
if (list != NULL)
{
for (i = 0; list[i] != NULL; i++)
{
slen += sizeof(char *);
slen += 8;
}
slen += sizeof(char *);
}
break;
}
case 'c':
{
if (largest < sizeof(char *)) largest = sizeof(char *);
csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
list = va_arg(ap, char **);
if (list != NULL)
{
for (i = 0; list[i] != NULL; i++)
{
slen += sizeof(char *);
slen += 16;
}
slen += sizeof(char *);
}
break;
}
case '@':
{
if (largest < 4) largest = 4;
csizep1 = 4 + padsize(hsize, 4, align);
slen = va_arg(ap, uint32_t);
if (largest < sizeof(char *)) largest = sizeof(char *);
csizep2 = sizeof(char *) + padsize(hsize + csizep1, sizeof(char *), align);
arg = va_arg(ap, char *);
csize = csizep1 + csizep2;
break;
}
default: return NULL;
}
memsize += csize;
memsize += slen;
hsize += csize;
}
va_end(ap);
pad = padsize(hsize, largest, align);
memsize += pad;
hsize += pad;
ils = malloc(memsize);
if (ils == NULL)
{
errno = ENOMEM;
return NULL;
}
dp = ils + hsize;
memcpy(dp, ILS_MAGIC, ILS_MAGIC_SIZE);
dp += ILS_MAGIC_SIZE;
hp = ils;
hsize = 0;
va_start(ap, fmt);
for (f = fmt; (*f) != '\0'; f++)
{
switch (*f)
{
case 's':
{
pad = padsize(hsize, sizeof(char *), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
arg = va_arg(ap, char *);
if (arg == NULL)
{
memset(hp, 0, sizeof(char *));
}
else
{
memcpy(hp, &dp, sizeof(char *));
slen = strlen(arg) + 1;
memcpy(dp, arg, slen);
dp += slen;
}
hp += sizeof(char *);
hsize += sizeof(char *);
break;
}
case '1':
{
u8 = va_arg(ap, int);
memcpy(hp, &u8, sizeof(uint8_t));
hp += sizeof(uint8_t);
break;
}
case '2':
{
pad = padsize(hsize, 2, align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
u16 = va_arg(ap, int);
memcpy(hp, &u16, sizeof(uint16_t));
hp += sizeof(uint16_t);
hsize += sizeof(uint16_t);
break;
}
case '4':
{
pad = padsize(hsize, 4, align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
u32 = va_arg(ap, uint32_t);
memcpy(hp, &u32, sizeof(uint32_t));
hp += sizeof(uint32_t);
hsize += sizeof(uint32_t);
break;
}
case '8':
{
pad = padsize(hsize, 8, align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
u64 = va_arg(ap, uint64_t);
memcpy(hp, &u64, sizeof(uint64_t));
hp += sizeof(uint64_t);
hsize += sizeof(uint64_t);
break;
}
case 'S':
{
pad = padsize(hsize, 4, align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
sdata = va_arg(ap, socket_data_t);
memcpy(hp, (char *)(sdata.x), sizeof(socket_data_t));
hp += sizeof(socket_data_t);
hsize += sizeof(socket_data_t);
break;
}
case 'L':
{
pad = padsize(hsize, sizeof(unsigned long), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
l = va_arg(ap, unsigned long);
memcpy(hp, &l, sizeof(unsigned long));
hp += sizeof(unsigned long);
hsize += sizeof(unsigned long);
break;
}
case 'm':
{
pad = padsize(hsize, sizeof(mach_port_t), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
m = va_arg(ap, mach_port_t);
memcpy(hp, &m, sizeof(mach_port_t));
hp += sizeof(mach_port_t);
hsize += sizeof(mach_port_t);
break;
}
case '*':
{
pad = padsize(hsize, sizeof(char *), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
list = va_arg(ap, char **);
memcpy(hp, &dp, sizeof(char *));
for (i = 0; list && list[i] != NULL; i++);
lp = dp;
dp += ((i + 1) * sizeof(char *));
for (i = 0; list && list[i] != NULL; i++)
{
memcpy(lp, &dp, sizeof(char *));
lp += sizeof(char *);
slen = strlen(list[i]) + 1;
memcpy(dp, list[i], slen);
dp += slen;
}
memset(lp, 0, sizeof(char *));
hp += sizeof(char *);
hsize += sizeof(char *);
break;
}
case 'a':
{
pad = padsize(hsize, sizeof(char *), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
list = va_arg(ap, char **);
if (list == NULL)
{
memset(hp, 0, sizeof(char *));
}
else
{
memcpy(hp, &dp, sizeof(char *));
for (i = 0; list[i] != NULL; i++);
lp = dp;
dp += ((i + 1) * sizeof(char *));
for (i = 0; list[i] != NULL; i++)
{
memcpy(lp, &dp, sizeof(char *));
lp += sizeof(char *);
slen = 4;
memcpy(dp, list[i], slen);
dp += slen;
}
memset(lp, 0, sizeof(char *));
}
hp += sizeof(char *);
hsize += sizeof(char *);
break;
}
case 'b':
{
pad = padsize(hsize, sizeof(char *), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
list = va_arg(ap, char **);
if (list == NULL)
{
memset(hp, 0, sizeof(char *));
}
else
{
memcpy(hp, &dp, sizeof(char *));
for (i = 0; list[i] != NULL; i++);
lp = dp;
dp += ((i + 1) * sizeof(char *));
for (i = 0; list[i] != NULL; i++)
{
memcpy(lp, &dp, sizeof(char *));
lp += sizeof(char *);
slen = 8;
memcpy(dp, list[i], slen);
dp += slen;
}
memset(lp, 0, sizeof(char *));
}
hp += sizeof(char *);
hsize += sizeof(char *);
break;
}
case 'c':
{
pad = padsize(hsize, sizeof(char *), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
list = va_arg(ap, char **);
if (list == NULL)
{
memset(hp, 0, sizeof(char *));
}
else
{
memcpy(hp, &dp, sizeof(char *));
for (i = 0; list[i] != NULL; i++);
lp = dp;
dp += ((i + 1) * sizeof(char *));
for (i = 0; list[i] != NULL; i++)
{
memcpy(lp, &dp, sizeof(char *));
lp += sizeof(char *);
slen = 16;
memcpy(dp, list[i], slen);
dp += slen;
}
memset(lp, 0, sizeof(char *));
}
hp += sizeof(char *);
hsize += sizeof(char *);
break;
}
case '@':
{
pad = padsize(hsize, 4, align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
slen = va_arg(ap, uint32_t);
memcpy(hp, &slen, sizeof(uint32_t));
hp += sizeof(uint32_t);
hsize += sizeof(uint32_t);
pad = padsize(hsize, sizeof(char *), align);
if (pad != 0)
{
memset(hp, 0, pad);
hp += pad;
hsize += pad;
}
arg = va_arg(ap, char *);
if (arg == NULL)
{
memset(hp, 0, sizeof(char *));
}
else
{
memcpy(hp, &dp, sizeof(char *));
memcpy(dp, arg, slen);
dp += slen;
}
hp += sizeof(char *);
hsize += sizeof(char *);
}
}
}
va_end(ap);
pad = padsize(hsize, largest, align);
if (pad > 0) memset(hp, 0, pad);
return ils;
}