exp_t * exp_list(exp_t *list, exp_t *exp) { ll_t *ll; if (list->ex_type != EX_LIST) { ll = ll_create(); if (ll == NULL) { log_die(EX_SOFTWARE, "exp_list: ll_create failed"); } if (LL_INSERT(ll, list) == -1) { log_die(EX_SOFTWARE, "exp_list: LL_INSERT failed"); } list = exp_create(EX_LIST, ll); } else { ll = list->ex_data; } if (LL_INSERT(ll, exp) == -1) { log_die(EX_SOFTWARE, "exp_list: LL_INSERT failed"); } return list; }
int dbt_db_expire(dbt_t *dbt) { int r; if (dbt_lock(dbt)) { return -1; } if (dbt->dbt_driver->dd_expire == NULL) { log_die(EX_SOFTWARE, "dbt_expire: driver %s doesn't support expire", dbt->dbt_driver->dd_name); } r = dbt->dbt_driver->dd_expire(dbt); if (r < 0 && cf_dbt_fatal_errors) { log_die(EX_SOFTWARE, "fatal database error"); } dbt_unlock(dbt); return r; }
jsmntok_t * json_tokenise(char *js) { jsmn_parser parser; jsmn_init(&parser); unsigned int n = JSON_TOKENS; jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * n); log_null(tokens); int ret = jsmn_parse(&parser, js, tokens, n); while (ret == JSMN_ERROR_NOMEM) { n = n * 2 + 1; tokens = realloc(tokens, sizeof(jsmntok_t) * n); log_null(tokens); ret = jsmn_parse(&parser, js, tokens, n); } if (ret == JSMN_ERROR_INVAL) log_die("jsmn_parse: invalid JSON string"); if (ret == JSMN_ERROR_PART) log_die("jsmn_parse: truncated JSON string"); return tokens; }
static void cf_load_functions(void) { cf_function_t *function; var_t *v; void *data; for(function = cf_functions; function->cf_type; ++function) { if(vtable_get(cf_config, function->cf_name)) { continue; } function->cf_callback(&data); if (data == NULL) { log_die(EX_CONFIG, "cf_load_functions: callback for " "\"%s\" failed", function->cf_name); } v = var_create(function->cf_type, function->cf_name, data, VF_KEEPNAME); if (v == NULL) { log_die(EX_CONFIG, "cf_load_functions: var_create " "failed"); } if(vtable_set(cf_config, v) == -1) { log_die(EX_CONFIG, "cf_load_functions: var_table_set " "failed"); } } return; }
int hitlist_register(char *name) { hitlist_t *hl; ll_t *keys; VAR_INT_T *create; VAR_INT_T *update; VAR_INT_T *count; VAR_INT_T *timeout; VAR_INT_T *extend; VAR_INT_T *cleanup; char *sum; char *table; char *value_field; char *expire_field; if (name == NULL) { log_die(EX_SOFTWARE, "hitlist_register: name is NULL"); } keys = cf_get_value(VT_LIST, HITLIST_NAME, name, "keys", NULL); create = cf_get_value(VT_INT, HITLIST_NAME, name, "create", NULL); update = cf_get_value(VT_INT, HITLIST_NAME, name, "update", NULL); count = cf_get_value(VT_INT, HITLIST_NAME, name, "count", NULL); timeout = cf_get_value(VT_INT, HITLIST_NAME, name, "timeout", NULL); extend = cf_get_value(VT_INT, HITLIST_NAME, name, "extend", NULL); cleanup = cf_get_value(VT_INT, HITLIST_NAME, name, "cleanup", NULL); sum = cf_get_value(VT_STRING, HITLIST_NAME, name, "sum", NULL); table = cf_get_value(VT_STRING, HITLIST_NAME, name, "table", NULL); value_field = cf_get_value(VT_STRING, HITLIST_NAME, name, "value_field", NULL); expire_field = cf_get_value(VT_STRING, HITLIST_NAME, name, "expire_field", NULL); if (keys == NULL) { log_die(EX_SOFTWARE, "hitlist_register: %s: need keys", name); } if (keys->ll_size == 0) { log_die(EX_CONFIG, "hitlist_register: %s: keys is empty", name); } hl = hitlist_create(name, keys, create, update, count, timeout, extend, cleanup, sum, table, value_field, expire_field); if (hl == NULL) { log_die(EX_SOFTWARE, "hitlist_register: hl_create failed"); } if (sht_insert(hitlists, name, hl)) { log_die(EX_SOFTWARE, "hitlist_register: sht_insert failed"); } acl_symbol_register(name, MS_ANY, hitlist_lookup, AS_CACHE); return 0; }
void cf_set_keylist(var_t *table, ll_t *keys, var_t *v) { char *key; var_t *sub; if (table == NULL) { table = cf_config; } /* * Last key queued belongs to var_t *v itself. */ key = LL_DEQUEUE(keys); if(keys->ll_size == 0) { /* * keys is created in cf_yacc.y and no longer needed. */ ll_delete(keys, NULL); if(v->v_name == NULL) { v->v_name = key; } if(vtable_set(table, v) == -1) { log_die(EX_CONFIG, "cf_set: vtable_set failed"); } return; } if((sub = vtable_lookup(table, key))) { cf_set_keylist(sub, keys, v); /* * key is strdupd in cf_yacc.y and no longer needed. */ free(key); return; } if ((sub = vtable_create(key, 0)) == NULL) { log_die(EX_CONFIG, "cf_setr: vtable_create failed"); } if(vtable_set(table, sub) == -1) { log_die(EX_CONFIG, "cf_set: vtable_set failed"); } cf_set_keylist(sub, keys, v); return; }
/** * @brief malloc wrapper * @param size Size in bytes to allocate * @return A pointer to the allocated memory * * A wrapper for the malloc() function that checks for error * conditions. */ void *xmalloc(size_t size) { void *vp; if (size == 0) { log_die(EINVAL, "xmalloc: invalid argument -- zero size"); } if ((vp = malloc(size)) == NULL) { log_die(ENOMEM, "xmalloc: error allocating %zu bytes", size); } return (vp); }
int server_init() { server_function_t *func; /* * Don't start the server if server_socket is empty */ if (!cf_control_socket) { log_debug("server_init: server_socket is empty: exit"); return 0; } /* * Load function table */ if (sht_init(&server_function_table, FUNC_BUCKETS, NULL)) { log_die(EX_SOFTWARE, "server_init: sht_init failed"); } for (func = server_functions; func->sf_name; ++func) { if (sht_insert(&server_function_table, func->sf_name, func)) { log_die(EX_SOFTWARE, "server_init: sht_insert failed"); } } /* * Create server socket */ server_socket = sock_listen(cf_control_socket, BACKLOG); if (server_socket == -1) { log_die(EX_SOFTWARE, "server_init: sock_listen failed"); } /* * Start server thread */ if (util_thread_create(&server_thread, server_main, NULL)) { log_error("server_init: util_thread_create failed"); return -1; } return 0; }
/** * @brief realloc wrapper * @param ptr A pointer to a memory block * @param newSize The new size * @return A pointer to a memory block with given size * * A wrapper for the realloc() function that checks for error * conditions. */ void *xrealloc(void *ptr, size_t newSize) { void *newPtr; if (ptr == NULL) { log_die(EINVAL, "xrealloc: invalid argument: a null pointer was passed"); } else if (newSize == 0) { log_die(EINVAL, "xrealloc: invalid argument: zero size -- use free"); } else { if ((newPtr = realloc(ptr, newSize)) == NULL) log_die(errno, "xrealloc: error changing memory block to %zu bytes", newSize); } return (newPtr); }
static void cf_load_symbols(void) { cf_symbol_t *symbol; var_t *v; for(symbol = cf_symbols; symbol->cs_name; ++symbol) { v = vtable_lookup(cf_config, symbol->cs_name); if(v == NULL) { continue; } switch(v->v_type) { case VT_INT: *(VAR_INT_T *) symbol->cs_ptr = *(VAR_INT_T *) v->v_data; break; case VT_FLOAT: *(VAR_FLOAT_T *) symbol->cs_ptr = *(VAR_FLOAT_T *) v->v_data; break; case VT_STRING: *((char **) symbol->cs_ptr) = (char *) v->v_data; break; default: log_die(EX_CONFIG, "cf_symbols_load: bad type"); } } return; }
void cf_init(void) { if (cf_filename == NULL) { cf_filename = defs_mopherd_conf; } //char buffer[4096]; cf_config = vtable_create("config", VF_KEEPNAME); if (cf_config == NULL) { log_die(EX_CONFIG, "cf_init: vtable_create failed"); } //var_dump(cf_config, buffer, sizeof(buffer)); //printf(buffer); cf_load_defaults(); cf_load_file(cf_filename); cf_load_functions(); cf_load_symbols(); return; }
void dbt_driver_register(dbt_driver_t *dd) { if (dd->dd_use_sql) { dd->dd_get = sql_db_get; dd->dd_set = sql_db_set; dd->dd_del = sql_db_del; dd->dd_walk = sql_db_walk; dd->dd_expire = sql_db_expire; } if (dd->dd_init) { dd->dd_init(); } if((sht_insert(dbt_drivers, dd->dd_name, dd)) == -1) { log_die(EX_SOFTWARE, "dbt_driver_register: sht_insert for " "driver \"%s\" failed", dd->dd_name); } log_info("dbt_driver_register: database driver \"%s\" registered", dd->dd_name); return; }
int dbt_db_set(dbt_t *dbt, var_t *record) { int r; if (dbt_lock(dbt)) { return -1; } if (dbt_sync) { client_sync(dbt, record); } r = dbt->dbt_driver->dd_set(dbt, record); if (r < 0 && cf_dbt_fatal_errors) { log_die(EX_SOFTWARE, "fatal database error"); } dbt_unlock(dbt); return r; }
int hitlist_init(void) { var_t *hitlist; ht_t *config; ht_pos_t pos; var_t *v; hitlist = cf_get(VT_TABLE, HITLIST_NAME, NULL); if (hitlist == NULL) { log_notice("hitlist_init: no lists configured"); return 0; } hitlists = sht_create(BUCKETS, free); if (hitlists == NULL) { log_die(EX_SOFTWARE, "hitlist_init: sht_create failed"); } config = hitlist->v_data; ht_start(config, &pos); while ((v = ht_next(config, &pos))) { if (hitlist_register(v->v_name)) { log_error("hitlist_init: hitlist_register failed"); return -1; } } return 0; }
char * json_fetch(char *url) { CURL *curl = curl_easy_init(); log_null(curl); curl_easy_setopt(curl, CURLOPT_URL, url); buf_t *buf = buf_size(NULL, BUFFER_SIZE); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fetch_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf); curl_easy_setopt(curl, CURLOPT_USERAGENT, "jsmn-example (https://github.com/alisdair/jsmn-example, [email protected])"); struct curl_slist *hs = curl_slist_append(NULL, "Accept: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hs); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) log_die("curl_easy_perform failed: %s", curl_easy_strerror(res)); curl_easy_cleanup(curl); curl_slist_free_all(hs); char *js = buf_tostr(buf); free(buf->data); free(buf); return js; }
static char * copy_argument(const char *arg) { bool inside_arg = true; size_t count = argument_maxSize; char *dest_buf = xmalloc(count + 1); char *dest = &dest_buf[0]; while (*arg && count > 1) { if (*arg == '\"') { inside_arg = false; break; } *dest++ = *arg++, count--; } *dest = '\0'; if (inside_arg) { free(dest_buf); if (! (count > 1)) log_die(EOVERFLOW, "copy_argument: fatal: result truncated!"); return (NULL); } return (dest_buf); }
void module_init(int glob, ...) { va_list ap; char *module_name; char *module_path; char buffer[BUFLEN]; module_list = ll_create(); if (module_list == NULL) { log_die(EX_SOFTWARE, "module_init: ll_create failed"); } module_path = cf_module_path? cf_module_path: defs_module_path; // Search modules in the filesystem if (glob) { module_glob(module_path); return; } // Load modules supplied in va_list va_start(ap, glob); for (;;) { module_name = va_arg(ap, char *); if (module_name == NULL) { break; } if (strlen(module_path) + strlen(module_name) + 2 > sizeof buffer) { log_die(EX_SOFTWARE, "module_init: buffer exhausted"); } strcpy(buffer, module_path); strcat(buffer, "/"); strcat(buffer, module_name); module_load(buffer); } va_end(ap); }
void exp_init(void) { exp_defs = sht_create(EXP_BUCKETS, NULL); if (exp_defs == NULL) { log_die(EX_SOFTWARE, "exp_init: sht_create failed"); } exp_garbage = ll_create(); if (exp_garbage == NULL) { log_die(EX_SOFTWARE, "exp_init: ll_create failed"); } return; }
/** * @brief calloc wrapper * @param elt_count Element count * @param elt_size Element size * @return A pointer to the allocated memory * * A wrapper for the calloc function that checks for error * conditions. calloc always initializes the allocated memory to 0's. */ void *xcalloc(size_t elt_count, size_t elt_size) { void *vp; if (elt_count == 0) { log_die(EINVAL, "xcalloc: invalid argument: element count is zero"); } else if (elt_size == 0) { log_die(EINVAL, "xcalloc: invalid argument: element size is zero"); } else if (SIZE_MAX / elt_count < elt_size) { log_die(0, "xcalloc: integer overflow"); } else { if ((vp = calloc(elt_count, elt_size)) == NULL) log_die(ENOMEM, "xcalloc: out of memory (allocating %zu bytes)", (elt_count * elt_size)); } return (vp); }
void cf_set_new(var_type_t type, char *name, void *data, int flags) { if (vtable_set_new(cf_config, type, name, data, flags)) { log_die(EX_SOFTWARE, "cf_set: vtable_set_new failed"); } return; }
msgmod_t * msgmod_create(msgmod_mod_t mod, msgmod_target_t target, ...) { msgmod_t *mm; va_list ap; exp_t *exp; mm = (msgmod_t *) malloc(sizeof (msgmod_t)); if (mm == NULL) { log_sys_die(EX_OSERR, "msgmod_create: malloc"); } mm->mm_callback = msgmod_get_callback(mod, target); if (mm->mm_callback == NULL) { acl_parser_error("syntax error (msgmod callback)"); // Not reached. return NULL; } mm->mm_args = ll_create(); if (mm->mm_args == NULL) { log_die(EX_SOFTWARE, "msgmod_create: ll_create failed"); } va_start(ap, target); while ((exp = va_arg(ap, exp_t *))) { if (LL_INSERT(mm->mm_args, exp) == -1) { log_die(EX_SOFTWARE, "msgmod_create: LL_INSERT failed"); } } return mm; }
/** * @brief Make an exact copy of a string * @param s Input string * @return A copy of the input string * * Make an exact copy of a string. The storage of the new string is * obtained with malloc(). The routine never returns NULL. */ char *xstrdup(const char *s) { size_t sz = 0; char *s_copy = NULL; int chars_printed = -1; if (s == NULL) { log_die(EINVAL, "xstrdup: invalid argument"); } else { sz = strlen(s) + 1; } if ((s_copy = malloc(sz)) == NULL) { log_die(ENOMEM, "xstrdup: error allocating %zu bytes", sz); } if ((chars_printed = snprintf(s_copy, sz, "%s", s)) == -1 || (size_t) chars_printed >= sz) { log_die(errno, "xstrdup: snprintf error (chars_printed = %d)", chars_printed); } return (s_copy); }
void exp_define(char *name, exp_t *exp) { if (sht_insert(exp_defs, name, exp)) { log_debug("exp_define: sht_insert failed"); log_die(EX_SOFTWARE, "Multiple definition of %s", name); } free(name); return; }
exp_t * exp_constant(var_type_t type, void *data, int flags) { var_t *v = NULL; v = var_create(type, NULL, data, flags); if (v == NULL) { log_die(EX_SOFTWARE, "exp_constant: var_create failed"); } return exp_create(EX_CONSTANT, v); }
exp_t * exp_parentheses(exp_t *exp) { exp_t *p; p = exp_create(EX_PARENTHESES, exp); if (p == NULL) { log_die(EX_SOFTWARE, "exp_parentheses: exp_create failed"); } return p; }
static int server_exec_cmd(int sock, char *cmd) { int argc = 0; char *argv[MAXARGS]; char *save, *p, *nil; server_function_t *sf; int r; log_debug("server_exec_cmd: %s", cmd); for (nil = cmd; (p = strtok_r(nil, " ", &save)) && argc < MAXARGS; nil = NULL, ++argc) { argv[argc] = p; } if (argc == MAXARGS) { server_reply(sock, "Too many arguments"); log_error("server_exec_cmd: Too many arguments"); return -1; } sf = sht_lookup(&server_function_table, argv[0]); if (sf == NULL) { sf = sht_lookup(&server_function_table, "help"); if (sf == NULL) { log_die(EX_SOFTWARE, "server_exec_cmd: help not found. This is impossible hence fatal."); } } r = sf->sf_callback(sock, argc, argv); switch (r) { case 0: server_reply(sock, "CLOSE"); break; case -1: log_error("server_exec_cmd: %s failed", argv[0]); server_reply(sock, "ERROR"); break; default: server_ok(sock); break; } return r; }
static void * module_symbol_load(void *handle, char *path, char *suffix, int die) { char symbol[BUFLEN]; char *error; int len; void *p; module_symbol_name(path, symbol, sizeof symbol); len = strlen(symbol); /* * Append _suffix */ if (sizeof symbol < len + strlen(suffix) + 2) { log_die(EX_SOFTWARE, "module_symbol_load: buffer exhausted"); } symbol[len++] = '_'; strcpy(symbol + len, suffix); /* * Clear existing error */ dlerror(); /* * Load symbol */ p = dlsym(handle, symbol); error = (char *) dlerror(); if (error == NULL) { return p; } if(die) { log_sys_die(EX_SOFTWARE, "module_symbol_load: dlsym: %s", error); } log_debug("module_symbol_load: dlsym: %s", error); return p; }
int spamd_init(void) { char **p; if (sock_rr_init(&spamd_srr, "spamd_socket")) { log_die(EX_SOFTWARE, "spamd_init: sock_rr_init failed"); } for (p = spamd_symbols; *p; ++p) { acl_symbol_register(*p, MS_OFF_EOM, spamd_query, AS_CACHE); } return 0; }
static char * copy_identifier(const char *id) { size_t count = identifier_maxSize; char *dest_buf = xmalloc(count + 1); char *dest = &dest_buf[0]; while ((isalnum(*id) || *id == '_') && count > 1) { *dest++ = *id++, count--; } *dest = '\0'; if (! (count > 1)) log_die(EOVERFLOW, "copy_identifier: fatal: result truncated!"); return (dest_buf); }
/** * @brief Duplicates a printf style format string * @return The result of the conversation * * Duplicates a printf style format string. The storage is obtained * with malloc() which means that it must be freed. */ char *Strdup_printf(const char *format, ...) { int my_vasprintf(char **ret, const char *format, va_list ap); va_list ap; int chars_printed; char *ret; va_start(ap, format); chars_printed = my_vasprintf(&ret, format, ap); va_end(ap); if (chars_printed < 0) { log_die(errno, "Strdup_printf: fatal error"); } return (ret); }