#include <sys_defs.h>
#include <sys/stat.h>
#include <string.h>
#include <msg.h>
#include <vstring.h>
#include <stringops.h>
#include <split_at.h>
#include <name_code.h>
#include <dict_db.h>
#include <dict_dbm.h>
#include <dict_cdb.h>
#include <dict_lmdb.h>
#include <warn_stat.h>
#include <mail_params.h>
#include <dict_proxy.h>
#include <data_redirect.h>
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
static const NAME_CODE data_redirect_map_types[] = {
DICT_TYPE_HASH, 1,
DICT_TYPE_BTREE, 1,
DICT_TYPE_DBM, 1,
DICT_TYPE_LMDB, 1,
DICT_TYPE_CDB, 1,
"sdbm", 1,
"dbz", 1,
0, 0,
};
static char *data_redirect_path(VSTRING *result, const char *path,
const char *log_type, const char *log_name)
{
struct stat st;
#define PATH_DELIMITER "/"
(void) sane_dirname(result, path);
if (stat(STR(result), &st) != 0 || st.st_uid == var_owner_uid) {
vstring_strcpy(result, path);
} else {
msg_warn("request to update %s %s in non-%s directory %s",
log_type, log_name, var_mail_owner, STR(result));
msg_warn("redirecting the request to %s-owned %s %s",
var_mail_owner, VAR_DATA_DIR, var_data_dir);
(void) sane_basename(result, path);
vstring_prepend(result, PATH_DELIMITER, sizeof(PATH_DELIMITER) - 1);
vstring_prepend(result, var_data_dir, strlen(var_data_dir));
}
return (STR(result));
}
char *data_redirect_file(VSTRING *result, const char *path)
{
if (path == STR(result))
msg_panic("data_redirect_file: result clobbers input");
return (data_redirect_path(result, path, "file", path));
}
char *data_redirect_map(VSTRING *result, const char *map)
{
const char *path;
const char *map_type;
size_t map_type_len;
#define MAP_DELIMITER ":"
if (map == STR(result))
msg_panic("data_redirect_map: result clobbers input");
path = strchr(map, MAP_DELIMITER[0]);
if (path != 0) {
map_type = map;
map_type_len = path - map;
path += 1;
} else {
map_type = var_db_type;
map_type_len = strlen(map_type);
path = map;
}
vstring_strncpy(result, map_type, map_type_len);
if (name_code(data_redirect_map_types, NAME_CODE_FLAG_NONE, STR(result))) {
data_redirect_path(result, path, "table", map);
} else {
vstring_strcpy(result, path);
}
vstring_prepend(result, MAP_DELIMITER, sizeof(MAP_DELIMITER) - 1);
vstring_prepend(result, map_type, map_type_len);
return (STR(result));
}
#ifdef TEST
#include <unistd.h>
#include <stdlib.h>
#include <vstring_vstream.h>
#include <mail_conf.h>
int main(int argc, char **argv)
{
VSTRING *inbuf = vstring_alloc(100);
VSTRING *result = vstring_alloc(100);
char *bufp;
char *cmd;
char *target;
char *junk;
mail_conf_read();
while (vstring_get_nonl(inbuf, VSTREAM_IN) != VSTREAM_EOF) {
bufp = STR(inbuf);
if (!isatty(0)) {
vstream_printf("> %s\n", bufp);
vstream_fflush(VSTREAM_OUT);
}
if (*bufp == '#')
continue;
if ((cmd = mystrtok(&bufp, " \t")) == 0) {
vstream_printf("usage: file path|map maptype:mapname\n");
vstream_fflush(VSTREAM_OUT);
continue;
}
target = mystrtokq(&bufp, " \t");
junk = mystrtok(&bufp, " \t");
if (strcmp(cmd, "file") == 0 && target && !junk) {
data_redirect_file(result, target);
vstream_printf("%s -> %s\n", target, STR(result));
} else if (strcmp(cmd, "map") == 0 && target && !junk) {
data_redirect_map(result, target);
vstream_printf("%s -> %s\n", target, STR(result));
} else {
vstream_printf("usage: file path|map maptype:mapname\n");
}
vstream_fflush(VSTREAM_OUT);
}
vstring_free(inbuf);
return (0);
}
#endif