#include <config.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/socket.h>
#include <errno.h>
#include "exitcodes.h"
#include "libcyr_cfg.h"
#include "util.h"
#include "xmalloc.h"
#define BEAUTYBUFSIZE 4096
const unsigned char convert_to_lowercase[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const unsigned char convert_to_uppercase[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
char *lcase(char* str)
{
char *scan = str;
while (*scan) {
*scan = TOLOWER(*scan);
scan++;
}
return (str);
}
char *ucase(char* str)
{
char *scan = str;
while (*scan) {
*scan = convert_to_uppercase[(unsigned char)(*scan)];
scan++;
}
return (str);
}
char *beautify_copy(char* dst, const char* src)
{
unsigned char c;
while (*src) {
c = *src++ & 0x7F;
if (!isprint(c)) {
*dst++ = '^';
if (c > ' ') {
c = '?';
} else {
c += '@';
}
}
*dst++ = c;
}
*dst = '\0';
return (dst);
}
char *beautify_string(const char* src)
{
static char *beautybuf = NULL;
static int beautysize = 0;
int len;
len = strlen(src) * 2 + 1;
if (beautysize < len) {
if (!beautysize) {
beautysize = len > BEAUTYBUFSIZE ? len : BEAUTYBUFSIZE;
beautybuf = xmalloc(beautysize);
} else {
beautysize *= 2;
if (len > beautysize) beautysize = len;
beautybuf = xrealloc(beautybuf, beautysize);
}
if (!beautybuf) {
beautysize = 0;
return "";
}
}
(void) beautify_copy(beautybuf, src);
return (beautybuf);
}
keyvalue *kv_bsearch(const char* key, keyvalue* kv, int nelem,
int (*cmpf) (const char *s1, const char *s2))
{
int top, mid = 0, bot, cmp = 0;
cmp = 1;
bot = 0;
top = nelem - 1;
while (top >= bot && (cmp = (*cmpf)(key, kv[mid = (bot + top) >> 1].key)))
if (cmp < 0) {
top = mid - 1;
} else {
bot = mid + 1;
}
return (cmp ? NULL : kv + mid);
}
int dir_hash_c(const char *name)
{
int c;
if (libcyrus_config_getswitch(CYRUSOPT_FULLDIRHASH)) {
unsigned char *pt;
unsigned int n;
enum {
DIR_X = 3,
DIR_Y = 5,
DIR_P = 23,
DIR_A = 'A'
};
n = 0;
pt = (unsigned char *)name;
while (*pt && *pt != '.') {
n = ((n << DIR_X) ^ (n >> DIR_Y)) ^ *pt;
++pt;
}
c = DIR_A + (n % DIR_P);
}
else {
c = tolower(*name);
if (!isascii(c) || !islower(c)) c = 'q';
}
return c;
}
int cyrus_close_sock(int fd)
{
shutdown(fd, SHUT_RD);
return close(fd);
}
void cyrus_reset_stdio()
{
int devnull = open("/dev/null", O_RDWR, 0);
if (devnull == -1) {
fatal("open() on /dev/null failed", EC_TEMPFAIL);
}
shutdown(0, SHUT_RD);
dup2(devnull, 0);
shutdown(1, SHUT_RD);
dup2(devnull, 1);
shutdown(2, SHUT_RD);
dup2(devnull, 2);
if (devnull > 2) close(devnull);
}
int create_tempfile()
{
int fd;
char pattern[2048];
const char *path = libcyrus_config_getstring(CYRUSOPT_TEMP_PATH);
if(snprintf(pattern, sizeof(pattern), "%s/cyrus_tmpfile_XXXXXX",
path) >= sizeof(pattern)){
fatal("temporary file pathname is too long in prot_flush",
EC_TEMPFAIL);
}
fd = mkstemp(pattern);
if(fd == -1) {
return -1;
} else if(unlink(pattern) == -1) {
close(fd);
return -1;
}
return fd;
}
int cyrus_mkdir(const char *path, mode_t mode __attribute__((unused)))
{
char *p = (char *) path;
int save_errno;
struct stat sbuf;
while ((p = strchr(p+1, '/'))) {
*p = '\0';
if (mkdir(path, 0755) == -1 && errno != EEXIST) {
save_errno = errno;
if (stat(path, &sbuf) == -1) {
errno = save_errno;
syslog(LOG_ERR, "IOERROR: creating directory %s: %m", path);
return -1;
}
}
*p = '/';
}
return 0;
}