/* C */
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
/* Losedows */
#include <fileapi.h>
/* local */
#include "utilities.h"
#include "iniparser.h"
#define BUFSIZE 4096
static const char *get_string(dictionary *ini, const char *key)
{
const char *value;
char *new_string;
size_t length;
value = iniparser_getstring(ini, key, NULL);
if (!value)
return NULL;
length = strlen(value);
new_string = dirtyalloc(length + 1);
memcpy(new_string, value, length + 1);
return new_string;
}
static enum bool_param get_bool(dictionary *ini, const char *key)
{
int value = iniparser_getboolean(ini, key, 2);
return value == 2 ? PARAM_NOT_GIVEN :
value == 1 ? PARAM_YES : PARAM_NO;
}
static size_t get_msg(dictionary *ini, const char **dest)
{
int nkeys, i;
const char **keys;
const char *line;
size_t msg_size = 0;
char *msg, *msg_pos;
nkeys = iniparser_getsecnkeys(ini, "MSG");
if (nkeys == 0) {
*dest = NULL;
return 0;
}
keys = dirtyalloc(nkeys * sizeof(const char*));
iniparser_getseckeys(ini, "MSG", keys);
for (i = 0; i < nkeys; i++)
msg_size += strlen(iniparser_getstring(ini, keys[i], "")) + 1;
msg = dirtyalloc(msg_size);
msg_pos = msg;
for (i = 0; i < nkeys; i++) {
line = iniparser_getstring(ini, keys[i], "");
while (*line)
*(msg_pos++) = *(line++);
*(msg_pos++) = '\n';
}
free(keys);
*(msg_pos - 1) = '\0';
*dest = msg;
/* Exclude terminating null byte from returned size */
return msg_size - 1;
}
static size_t get_list(dictionary *ini, const char *section,
const char ***dest)
{
int nkeys, i;
const char **keys, **items;
const char *line;
char *copied_line;
size_t length;
nkeys = iniparser_getsecnkeys(ini, section);
if (nkeys == 0) {
*dest = NULL;
return 0;
}
keys = dirtyalloc(nkeys * sizeof(const char *));
items = dirtyalloc(nkeys * sizeof(const char *));
iniparser_getseckeys(ini, section, keys);
for (i = 0; i < nkeys; i++) {
line = iniparser_getstring(ini, keys[i], "");
length = strlen(line) + 1;
copied_line = dirtyalloc(length);
memcpy(copied_line, line, length);
items[i] = copied_line;
}
free(keys);
*dest = items;
return nkeys;
}
static dictionary *check_file_and_load_ini(const char *filename)
{
int retval;
char full_pathname[BUFSIZE];
dictionary *ini;
retval = GetFullPathName(filename, BUFSIZE, full_pathname, NULL);
if (retval == 0)
FAIL(MSG_CONF_PATH_EXPAND_FAIL, filename);
if (access(full_pathname, F_OK) != 0)
FAIL(MSG_CONF_NOT_EXIST, full_pathname);
if (access(full_pathname, R_OK) != 0)
FAIL(MSG_CONF_NOT_READABLE, full_pathname);
ini = iniparser_load(full_pathname);
if (!ini)
FAIL(MSG_INVALID_INI_FILE, full_pathname);
return ini;
}
void print_config(struct config *config);
void read_config(const char *filename, struct config *config)
{
dictionary *ini;
ini = check_file_and_load_ini(filename);
memset(config, '\0', sizeof(struct config)); /* not really needed */
config->host = get_string(ini, "SERVER:host");
config->login = get_string(ini, "SERVER:login");
config->password = get_string(ini, "SERVER:password");
config->dest_dir = get_string(ini, "SERVER:outputdir");
config->reply_to = get_string(ini, "MAIL:replyto");
config->from = get_string(ini, "MAIL:from");
if (!config->reply_to)
config->reply_to = get_string(ini, "SERVER:replyto");
if (!config->from)
config->from = get_string(ini, "SERVER:from");
config->subject = get_string(ini, "MAIL:subject");
config->use_SSL = get_bool(ini, "SERVER:ssl");
config->use_AUTH = get_bool(ini, "SERVER:auth");
config->del_msgs = get_bool(ini, "SERVER:delete_msg");
config->save_body = get_bool(ini, "SERVER:save_body");
config->save_subj = get_bool(ini, "SERVER:save_subject");
config->port_POP3 = iniparser_getint(ini, "SERVER:port_pop3", -1);
config->port_SMTP = iniparser_getint(ini, "SERVER:port_smtp", -1);
config->timeout = iniparser_getint(ini, "SERVER:timeout", 1000000);
config->nfiles = get_list(ini, "FILES", &config->files);
config->nto = get_list(ini, "CC", &config->to);
config->msg_size = get_msg (ini, &config->msg_body);
iniparser_freedict(ini);
/* print_config(config); */
}
void get_config(int argc, const char **argv, struct config *config)
{
int config_arg_idx = 1;
if (argc < 2)
goto bad_args;
if (strcmp(argv[1], "--wide-chars") == 0) {
config_arg_idx = 2;
iniparser_set_fgetc_impl(provisional_wide_char_fgetc);
}
if (argc <= config_arg_idx)
goto bad_args;
iniparser_set_error_callback(dummy_errback);
iniparser_set_process_multiline(false);
read_config(argv[config_arg_idx], config);
return;
bad_args:
FAIL(MSG_BAD_ARGS_NUM, argv[0]);
}
void free_config(struct config *config)
{
//TODO
}
void print_config(struct config *config)
{
size_t i;
if (config->host)
printf("host: %s\n", config->host);
else
puts("host not set");
if (config->login)
printf("login: %s\n", config->login);
else
puts("login not set");
if (config->password)
printf("password: %s\n", config->password);
else
puts("password not set");
if (config->reply_to)
printf("reply_to: %s\n", config->reply_to);
else
puts("reply_to not set");
if (config->from)
printf("from: %s\n", config->from);
else
puts("from not set");
if (config->dest_dir)
printf("dest_dir: %s\n", config->dest_dir);
else
puts("dest_dir not set");
if (config->subject)
printf("subject: %s\n", config->subject);
else
puts("subject not set");
printf("SSL: %s\n", config->use_SSL ? "True" : "False");
printf("AUTH: %s\n", config->use_AUTH ? "True" : "False");
printf("port_POP3: %d\n", config->port_POP3);
printf("port_SMTP: %d\n", config->port_SMTP);
printf("timeout: %d\n", config->timeout);
printf("delete: %s\n", config->del_msgs ? "True" : "False");
printf("save_body: %s\n", config->save_body ? "True" : "False");
printf("save_subject: %s\n", config->save_subj ? "True" : "False");
if (config->nfiles) {
puts("files:");
for (i = 0; i < config->nfiles; i++)
printf(" %s\n", config->files[i]);
} else {
puts("no files");
}
if (config->nto) {
puts("recipients:");
for (i = 0; i < config->nto; i++)
printf(" %s\n", config->to[i]);
} else {
puts("no recipients");
}
if (config->msg_body) {
printf("message (length %lu):\n",
(unsigned long)config->msg_size);
puts(config->msg_body);
} else {
puts("no message");
}
}