#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define _PATH_ASL_IN "/var/run/asl_input"
static uint8_t *b64charset = (uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
__private_extern__ int
_asl_server_socket(int *sock, struct sockaddr_un *server)
{
socklen_t len;
int status, flags;
*sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (*sock < 0) return -1;
memset(server, 0, sizeof(struct sockaddr_un));
server->sun_family = AF_UNIX;
strcpy(server->sun_path, _PATH_ASL_IN);
server->sun_len = strlen(server->sun_path) + 1;
len = sizeof(server->sun_len) + sizeof(server->sun_family) + server->sun_len;
status = connect(*sock, (const struct sockaddr *)server, len);
if (status < 0)
{
close(*sock);
*sock = -1;
return -1;
}
fcntl(*sock, F_SETFD, 1);
flags = fcntl(*sock, F_GETFL, 0);
if (flags >= 0) fcntl(*sock, F_SETFL, flags | O_NONBLOCK);
return 0;
}
__private_extern__ const char *
_asl_escape(unsigned char c)
{
switch(c)
{
case '\\':
return "\\\\";
case '[':
return "\\[";
case ']':
return "\\]";
case '\n':
return "\\n";
}
return NULL;
}
static int
asl_is_utf8_char(const unsigned char *p, int *state, int *ctype)
{
switch (*state)
{
case 0:
{
*ctype = 0;
if (*p >= 0x80)
{
*state = 1;
if ((*p >= 0xc2) && (*p <= 0xdf)) *ctype = 1;
else if (*p == 0xe0) *ctype = 2;
else if ((*p >= 0xe1) && (*p <= 0xef)) *ctype = 3;
else if (*p == 0xf0) *ctype = 4;
else if ((*p >= 0xf1) && (*p <= 0xf3)) *ctype = 5;
else if (*p == 0xf4) *ctype = 6;
else return 0;
}
break;
}
case 1:
{
switch (*ctype)
{
case 1:
{
if ((*p >= 0x80) && (*p <= 0xbf)) *state = 0;
else return 0;
break;
}
case 2:
{
if ((*p >= 0xa0) && (*p <= 0xbf)) *state = 2;
else return 0;
break;
}
case 3:
{
if ((*p >= 0x80) && (*p <= 0xbf)) *state = 2;
else return 0;
break;
}
case 4:
{
if ((*p >= 0x90) && (*p <= 0xbf)) *state = 2;
else return 0;
break;
}
case 5:
{
if ((*p >= 0x80) && (*p <= 0xbf)) *state = 2;
else return 0;
break;
}
case 6:
{
if ((*p >= 0x80) && (*p <= 0x8f)) *state = 2;
else return 0;
break;
}
default: return 0;
}
break;
}
case 2:
{
if ((*ctype >= 2) && (*ctype <= 3))
{
if ((*p >= 0x80) && (*p <= 0xbf)) *state = 0;
else return 0;
}
else if ((*ctype >= 4) && (*ctype <= 6))
{
if ((*p >= 0x80) && (*p <= 0xbf)) *state = 3;
else return 0;
}
else
{
return 0;
}
break;
}
case 3:
{
if ((*ctype >= 4) && (*ctype <= 6))
{
if ((*p >= 0x80) && (*p <= 0xbf)) *state = 0;
else return 0;
}
else
{
return 0;
}
break;
}
default: return 0;
}
return 1;
}
__private_extern__ int
asl_is_utf8(const char *str)
{
const unsigned char *p;
int flag = 1;
int state = 0;
int ctype = 0;
if (str == NULL) return flag;
for (p = (const unsigned char *)str; (*p != '\0') && (flag == 1); p++)
{
flag = asl_is_utf8_char(p, &state, &ctype);
}
return flag;
}
__private_extern__ uint8_t *
asl_b64_encode(const uint8_t *buf, size_t len)
{
uint8_t *out;
uint8_t b;
size_t i0, i1, i2, j, outlen;
if (buf == NULL) return NULL;
if (len == 0) return NULL;
outlen = ((len + 2) / 3) * 4;
out = (uint8_t *)malloc(outlen + 1);
if (out == NULL)
{
errno = ENOMEM;
return NULL;
}
out[outlen] = 0;
i0 = 0;
i1 = 1;
i2 = 2;
j = 0;
while (i2 < len)
{
b = buf[i0] >> 2;
out[j++] = b64charset[b];
b = ((buf[i0] & 0x03) << 4) | (buf[i1] >> 4);
out[j++] = b64charset[b];
b = ((buf[i1] & 0x0f) << 2) | ((buf[i2] & 0xc0) >> 6);
out[j++] = b64charset[b];
b = buf[i2] & 0x3f;
out[j++] = b64charset[b];
i0 += 3;
i1 = i0 + 1;
i2 = i1 + 1;
}
if (i0 < len)
{
b = buf[i0] >> 2;
out[j++] = b64charset[b];
b = (buf[i0] & 0x03) << 4;
if (i1 < len) b |= (buf[i1] >> 4);
out[j++] = b64charset[b];
if (i1 >= len)
{
out[j++] = '=';
out[j++] = '=';
return out;
}
b = (buf[i1] & 0x0f) << 2;
out[j++] = b64charset[b];
out[j++] = '=';
}
return out;
}