From 611c19fafa093386ec1b6321a4f8cad1c793df6e Mon Sep 17 00:00:00 2001 From: Kaian Date: Mon, 26 Nov 2018 20:04:58 +0100 Subject: [PATCH] core: merge alias and column configuration into settings --- CMakeLists.txt | 1 - src/Makefile.am | 1 - src/attribute.c | 48 +- src/attribute.h | 11 - src/main.c | 28 +- src/ncurses/manager.c | 2 + src/ncurses/windows/auth_validate_win.c | 2 +- src/ncurses/windows/call_flow_win.c | 28 +- src/ncurses/windows/call_flow_win.h | 2 +- src/ncurses/windows/call_list_win.c | 43 +- src/ncurses/windows/call_list_win.h | 4 +- src/ncurses/windows/column_select_win.c | 13 +- src/ncurses/windows/filter_win.c | 4 +- src/ncurses/windows/msg_diff_win.c | 2 +- src/ncurses/windows/save_win.c | 14 +- src/ncurses/windows/settings_win.c | 7 +- src/ncurses/windows/settings_win.h | 2 +- src/option.c | 214 --------- src/option.h | 161 ------- src/setting.c | 572 +++++++++++++++++++----- src/setting.h | 190 ++++++-- 21 files changed, 696 insertions(+), 653 deletions(-) delete mode 100644 src/option.c delete mode 100644 src/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a05d54..03df5e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ set(SOURCES src/filter.c src/group.c src/main.c - src/option.c src/stream.c src/setting.c src/attribute.c diff --git a/src/Makefile.am b/src/Makefile.am index 9484763..c6c170f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,4 +54,3 @@ sngrep_SOURCES+=capture/capture.c sngrep_SOURCES+=capture/capture_txt.c sngrep_SOURCES+=capture/capture_pcap.c sngrep_SOURCES+=filter.c -sngrep_SOURCES+=option.c diff --git a/src/attribute.c b/src/attribute.c index d883803..3916a46 100644 --- a/src/attribute.c +++ b/src/attribute.c @@ -32,25 +32,25 @@ #include "ncurses/manager.h" static AttributeHeader attrs[ATTR_COUNT] = { - { ATTR_CALLINDEX, "index", "Idx", "Call Index", 4 , NULL }, - { ATTR_SIPFROM, "sipfrom", NULL, "SIP From", 25, NULL }, - { ATTR_SIPFROMUSER, "sipfromuser", NULL, "SIP From User", 20, NULL }, - { ATTR_SIPTO, "sipto", NULL, "SIP To", 25, NULL }, - { ATTR_SIPTOUSER, "siptouser", NULL, "SIP To User", 20, NULL }, - { ATTR_SRC, "src", NULL, "Source", 22, NULL }, - { ATTR_DST, "dst", NULL, "Destination", 22, NULL }, - { ATTR_CALLID, "callid", NULL, "Call-ID", 50, NULL }, - { ATTR_XCALLID, "xcallid", NULL, "X-Call-ID", 50, NULL }, - { ATTR_DATE, "date", NULL, "Date", 10, NULL }, - { ATTR_TIME, "time", NULL, "Time", 8, NULL }, - { ATTR_METHOD, "method", NULL, "Method", 10, attr_color_sip_method }, - { ATTR_TRANSPORT, "transport", "Trans", "Transport", 3, NULL }, - { ATTR_MSGCNT, "msgcnt", "Msgs", "Message Count", 5, NULL }, - { ATTR_CALLSTATE, "state", NULL, "Call State", 10, attr_color_call_state }, - { ATTR_CONVDUR, "convdur", "ConvDur", "Conversation Duration", 7, NULL }, - { ATTR_TOTALDUR, "totaldur", "TotalDur", "Total Duration", 8, NULL }, - { ATTR_REASON_TXT, "reason", "Reason Text", "Reason Text", 25, NULL }, - { ATTR_WARNING, "warning", "Warning", "Warning code", 4, NULL } + { ATTR_CALLINDEX, "index", "Idx", "Call Index", NULL }, + { ATTR_SIPFROM, "sipfrom", NULL, "SIP From", NULL }, + { ATTR_SIPFROMUSER, "sipfromuser", NULL, "SIP From User", NULL }, + { ATTR_SIPTO, "sipto", NULL, "SIP To", NULL }, + { ATTR_SIPTOUSER, "siptouser", NULL, "SIP To User", NULL }, + { ATTR_SRC, "src", NULL, "Source", NULL }, + { ATTR_DST, "dst", NULL, "Destination", NULL }, + { ATTR_CALLID, "callid", NULL, "Call-ID", NULL }, + { ATTR_XCALLID, "xcallid", NULL, "X-Call-ID", NULL }, + { ATTR_DATE, "date", NULL, "Date", NULL }, + { ATTR_TIME, "time", NULL, "Time", NULL }, + { ATTR_METHOD, "method", NULL, "Method", attr_color_sip_method }, + { ATTR_TRANSPORT, "transport", "Trans", "Transport", NULL }, + { ATTR_MSGCNT, "msgcnt", "Msgs", "Message Count", NULL }, + { ATTR_CALLSTATE, "state", NULL, "Call State", attr_color_call_state }, + { ATTR_CONVDUR, "convdur", "ConvDur", "Conversation Duration", NULL }, + { ATTR_TOTALDUR, "totaldur", "TotalDur", "Total Duration", NULL }, + { ATTR_REASON_TXT, "reason", "Reason Text", "Reason Text", NULL }, + { ATTR_WARNING, "warning", "Warning", "Warning code", NULL } }; AttributeHeader * @@ -91,16 +91,6 @@ attr_name(enum AttributeId id) return NULL; } -gint -attr_width(enum AttributeId id) -{ - AttributeHeader *header; - if ((header = attr_header(id))) { - return header->dwidth; - } - return 0; -} - gint attr_find_by_name(const gchar *name) { diff --git a/src/attribute.h b/src/attribute.h index 1dc1b9a..600ada1 100644 --- a/src/attribute.h +++ b/src/attribute.h @@ -106,8 +106,6 @@ struct _AttributeHeader { gchar *title; //! Attribute description gchar *desc; - //! Attribute default display width - guint dwidth; //! This function determines the color of this attribute in CallList int (*color)(const char *value); }; @@ -169,15 +167,6 @@ attr_title(enum AttributeId id); const gchar * attr_name(enum AttributeId id); -/** - * @brief Get Attribute prefered display width - * - * @param id Attribute id - * @return prefered attribute width - */ -int -attr_width(enum AttributeId id); - /** * @brief Get Attribute id from its name * diff --git a/src/main.c b/src/main.c index 317c787..3d40ac3 100644 --- a/src/main.c +++ b/src/main.c @@ -28,7 +28,7 @@ #include "config.h" #include -#include "option.h" +#include "setting.h" #include "capture/capture.h" #include "ncurses/manager.h" #ifdef USE_HEP @@ -147,23 +147,13 @@ main(int argc, char* argv[]) return 1; } - // Parse command line arguments that have high priority - if (version) { - print_version_info(); - return 0; - } else if (config_dump) { - key_bindings_dump(); - settings_dump(); - return 0; - } - /***************************** Configuration *****************************/ // Initialize configuration options - init_options(no_config); + settings_init(no_config); // Override default configuration options if requested if (config_file) - read_options(config_file); + setting_read_file(config_file); // Get initial values for configurable arguments if (!storage_mopts.invite) @@ -183,6 +173,16 @@ main(int argc, char* argv[]) if (!keyfile) keyfile = g_strdup(setting_get_value(SETTING_CAPTURE_KEYFILE)); #endif + // Parse command line arguments that have high priority + if (version) { + print_version_info(); + return 0; + } else if (config_dump) { + key_bindings_dump(); + settings_dump(); + return 0; + } + /***************************** Capture Inputs *****************************/ // Main packet capture manager manager = capture_manager_new(); @@ -348,7 +348,7 @@ main(int argc, char* argv[]) ncurses_deinit(); // Deinitialize configuration options - deinit_options(); + settings_deinit(); // Deallocate sip stored messages storage_deinit(); diff --git a/src/ncurses/manager.c b/src/ncurses/manager.c index 9662d3f..c63e65d 100644 --- a/src/ncurses/manager.c +++ b/src/ncurses/manager.c @@ -231,8 +231,10 @@ ncurses_find_by_type(enum WindowTypes type) break; case WINDOW_SETTINGS: window = settings_win_new(); + break; case WINDOW_AUTH_VALIDATE: window = auth_validate_win_new(); + break; default: break; } diff --git a/src/ncurses/windows/auth_validate_win.c b/src/ncurses/windows/auth_validate_win.c index e3282f3..a821a6a 100644 --- a/src/ncurses/windows/auth_validate_win.c +++ b/src/ncurses/windows/auth_validate_win.c @@ -368,7 +368,7 @@ auth_validate_win_new() form_opts_off(info->form, O_BS_OVERLOAD); // Set Default field values - char savepath[MAX_SETTING_LEN]; + char savepath[SETTING_MAX_LEN]; sprintf(savepath, "%s", setting_get_value(SETTING_SAVEPATH)); set_field_buffer(info->fields[FLD_AUTH_CLOSE], 0, "[ Close ]"); diff --git a/src/ncurses/windows/call_flow_win.c b/src/ncurses/windows/call_flow_win.c index 8feede1..1f50805 100644 --- a/src/ncurses/windows/call_flow_win.c +++ b/src/ncurses/windows/call_flow_win.c @@ -40,7 +40,7 @@ #include "save_win.h" #include "timeval.h" #include "glib-utils.h" -#include "option.h" +#include "setting.h" /*** * @@ -170,7 +170,7 @@ call_flow_arrow_filter(void *item) if (setting_enabled(SETTING_CF_MEDIA)) return 1; // Otherwise only show active streams - if (setting_has_value(SETTING_CF_MEDIA, SETTING_ACTIVE)) + if (setting_has_value(SETTING_CF_MEDIA, "active")) return stream_is_active(arrow->item); } @@ -361,7 +361,7 @@ call_flow_column_get_starting(Window *window, G_GNUC_UNUSED const char *callid, gboolean match_port = addr.port != 0; // Get alias value for given address - const gchar *alias = get_alias_value(addr.ip); + const gchar *alias = setting_get_alias(addr.ip); for (guint i = start; i < g_ptr_array_len(info->columns); i++) { CallFlowColumn *column = g_ptr_array_index(info->columns, i); @@ -427,7 +427,7 @@ call_flow_column_new(Address addr) // Create a new column CallFlowColumn * column = g_malloc0(sizeof(CallFlowColumn)); column->addr = addr; - column->alias = g_strdup(get_alias_value(addr.ip)); + column->alias = setting_get_alias(addr.ip); return column; } @@ -546,7 +546,7 @@ call_flow_draw_columns(Window *window) { Call *call = NULL; RtpStream *stream; - char coltext[MAX_SETTING_LEN]; + char coltext[SETTING_MAX_LEN]; Address addr; // Get panel information @@ -592,22 +592,22 @@ call_flow_draw_columns(Window *window) } if (setting_enabled(SETTING_CF_SPLITCALLID) || !column->addr.port) { - snprintf(coltext, MAX_SETTING_LEN, "%s", column->alias); + snprintf(coltext, SETTING_MAX_LEN, "%s", column->alias); } else if (setting_enabled(SETTING_DISPLAY_ALIAS)) { if (strlen(column->addr.ip) > 15) { - snprintf(coltext, MAX_SETTING_LEN, "..%.*s:%hu", - MAX_SETTING_LEN - 7, column->alias + strlen(column->alias) - 13, column->addr.port); + snprintf(coltext, SETTING_MAX_LEN, "..%.*s:%hu", + SETTING_MAX_LEN - 7, column->alias + strlen(column->alias) - 13, column->addr.port); } else { - snprintf(coltext, MAX_SETTING_LEN, "%.*s:%hu", - MAX_SETTING_LEN - 7, column->alias, column->addr.port); + snprintf(coltext, SETTING_MAX_LEN, "%.*s:%hu", + SETTING_MAX_LEN - 7, column->alias, column->addr.port); } } else { if (strlen(column->addr.ip) > 15) { - snprintf(coltext, MAX_SETTING_LEN, "..%.*s:%hu", - MAX_SETTING_LEN - 7, column->addr.ip + strlen(column->addr.ip) - 13, column->addr.port); + snprintf(coltext, SETTING_MAX_LEN, "..%.*s:%hu", + SETTING_MAX_LEN - 7, column->addr.ip + strlen(column->addr.ip) - 13, column->addr.port); } else { - snprintf(coltext, MAX_SETTING_LEN, "%.*s:%hu", - MAX_SETTING_LEN - 7, column->addr.ip, column->addr.port); + snprintf(coltext, SETTING_MAX_LEN, "%.*s:%hu", + SETTING_MAX_LEN - 7, column->addr.ip, column->addr.port); } } diff --git a/src/ncurses/windows/call_flow_win.h b/src/ncurses/windows/call_flow_win.h index d780750..44716c1 100644 --- a/src/ncurses/windows/call_flow_win.h +++ b/src/ncurses/windows/call_flow_win.h @@ -123,7 +123,7 @@ struct _CallFlowColumn { //! Address header for this column Address addr; //! Alias for the given address - gchar *alias; + const gchar *alias; //! Call Ids GList *callids; }; diff --git a/src/ncurses/windows/call_list_win.c b/src/ncurses/windows/call_list_win.c index f033295..331699a 100644 --- a/src/ncurses/windows/call_list_win.c +++ b/src/ncurses/windows/call_list_win.c @@ -34,7 +34,7 @@ #include #include #include "glib-utils.h" -#include "option.h" +#include "setting.h" #include "filter.h" #include "capture/capture_pcap.h" #ifdef USE_HEP @@ -1082,6 +1082,14 @@ call_list_help(G_GNUC_UNUSED Window *window) return 0; } +static gint +call_list_column_sorter(const CallListColumn **a, const CallListColumn **b) +{ + if ((*a)->position > (*b)->position) return 1; + if ((*a)->position < (*b)->position) return -1; + return 0; +} + /** * @brief Add a column the Call List * @@ -1096,7 +1104,7 @@ call_list_help(G_GNUC_UNUSED Window *window) */ static void call_list_add_column(Window *window, enum AttributeId id, const char* attr, - const char *title, int width) + const char *title, gint position, int width) { CallListWinInfo *info = call_list_info(window); g_return_if_fail(info != NULL); @@ -1105,7 +1113,8 @@ call_list_add_column(Window *window, enum AttributeId id, const char* attr, column->id = id; column->attr = attr; column->title = title; - column->width = (guint) width; + column->position = position; + column->width = width; g_ptr_array_add(info->columns, column); } @@ -1177,27 +1186,21 @@ call_list_win_new() // Add configured columns info->columns = g_ptr_array_new_with_free_func(g_free); - for (guint i = 0; i < ATTR_COUNT; i++) { + for (guint attr_id = 0; attr_id < ATTR_COUNT; attr_id++) { // Get column attribute name from options - gchar *option = g_strdup_printf("cl.column%d", i); - const gchar *field = NULL; - if ((field = get_option_value(option)) != NULL) { - gint attrid, collen; - if ((attrid = attr_find_by_name(field)) == -1) - continue; + gint position = setting_column_pos(attr_id); + // Check column is visible + if (position == -1) continue; - // Get column width from options - sprintf(option, "cl.column%d.width", i); - if ((collen = get_option_int_value(option)) == -1) - collen = attr_width(attrid); + // Get column information + gint collen = setting_column_width(attr_id); + const gchar *title = attr_title(attr_id); + const gchar *field = attr_name(attr_id); - // Get column title - const gchar *title = attr_title(attrid); - // Add column to the list - call_list_add_column(window, attrid, field, title, collen); - } - g_free(option); + // Add column to the list + call_list_add_column(window, attr_id, field, title, position, collen); } + g_ptr_array_sort(info->columns, (GCompareFunc) call_list_column_sorter); // Initialize the fields info->fields[FLD_LIST_FILTER] = new_field(1, window->width - 19, 3, 18, 0, 0); diff --git a/src/ncurses/windows/call_list_win.h b/src/ncurses/windows/call_list_win.h index f6e448c..30273d7 100644 --- a/src/ncurses/windows/call_list_win.h +++ b/src/ncurses/windows/call_list_win.h @@ -66,8 +66,10 @@ struct _CallListColumn { const char *attr; //! Column title const char *title; + //! Current column position + gint position; //! Current width - guint width; + gint width; }; /** diff --git a/src/ncurses/windows/column_select_win.c b/src/ncurses/windows/column_select_win.c index 913142e..9736414 100644 --- a/src/ncurses/windows/column_select_win.c +++ b/src/ncurses/windows/column_select_win.c @@ -177,7 +177,7 @@ column_select_update_columns(Window *ui) column->id = attr_id; column->attr = attr_name(attr_id); column->title = attr_title(attr_id); - column->width = (guint) attr_width(attr_id); + column->width = setting_column_width(attr_id); g_ptr_array_add(info->selected, column); } } @@ -257,11 +257,12 @@ column_select_save_columns(Window *ui) // Add all selected columns for (gint i = 0; i < item_count(info->menu); i++) { // If column is active - if (!strncmp(item_name(info->items[i]), "[ ]", 3)) - continue; - - // Add the columns settings - g_fprintf(fo, "set cl.column%d %s\n", i, (const char*) item_userptr(info->items[i])); + if (!strncmp(item_name(info->items[i]), "[ ]", 3)) { + g_fprintf(fo, "set cl.column.%s.pos -1\n", (const char*) item_userptr(info->items[i])); + } else { + // Add the columns settings + g_fprintf(fo, "set cl.column.%s.pos %d\n", (const char *) item_userptr(info->items[i]), i); + } } fclose(fo); diff --git a/src/ncurses/windows/filter_win.c b/src/ncurses/windows/filter_win.c index dc5cd60..f3b90a3 100644 --- a/src/ncurses/windows/filter_win.c +++ b/src/ncurses/windows/filter_win.c @@ -113,7 +113,7 @@ filter_field_method(int field_id) static void filter_save_options(Window *ui) { - char field_value[MAX_SETTING_LEN]; + char field_value[SETTING_MAX_LEN]; char *expr; int field_id; char method_expr[256]; @@ -201,7 +201,7 @@ static int filter_handle_key(Window *ui, int key) { int field_idx; - char field_value[MAX_SETTING_LEN]; + char field_value[SETTING_MAX_LEN]; // Get panel information FilterWinInfo *info = filter_info(ui); diff --git a/src/ncurses/windows/msg_diff_win.c b/src/ncurses/windows/msg_diff_win.c index 3aba438..d2c0cf7 100644 --- a/src/ncurses/windows/msg_diff_win.c +++ b/src/ncurses/windows/msg_diff_win.c @@ -29,7 +29,7 @@ #include #include #include "msg_diff_win.h" -#include "option.h" +#include "setting.h" /*** * diff --git a/src/ncurses/windows/save_win.c b/src/ncurses/windows/save_win.c index c450d68..f95bf7b 100644 --- a/src/ncurses/windows/save_win.c +++ b/src/ncurses/windows/save_win.c @@ -68,7 +68,7 @@ save_info(Window *window) static int save_draw(Window *window) { - char field_value[MAX_SETTING_LEN]; + char field_value[SETTING_MAX_LEN]; // Get panel information SaveWinInfo *info = save_info(window); @@ -148,9 +148,9 @@ save_packet_cb(Packet *packet, CaptureOutput *output) static int save_to_file(Window *window) { - char savepath[MAX_SETTING_LEN]; - char savefile[MAX_SETTING_LEN]; - char fullfile[MAX_SETTING_LEN*2]; + char savepath[SETTING_MAX_LEN]; + char savefile[SETTING_MAX_LEN]; + char fullfile[SETTING_MAX_LEN*2]; CaptureOutput *output = NULL; int cur = 0, total = 0; WINDOW *progress; @@ -530,8 +530,8 @@ save_win_new() field_opts_off(info->fields[FLD_SAVE_MESSAGE], O_VISIBLE); // Limit max save path and file length - set_max_field(info->fields[FLD_SAVE_PATH], MAX_SETTING_LEN); - set_max_field(info->fields[FLD_SAVE_FILE], MAX_SETTING_LEN); + set_max_field(info->fields[FLD_SAVE_PATH], SETTING_MAX_LEN); + set_max_field(info->fields[FLD_SAVE_FILE], SETTING_MAX_LEN); // Change background of input fields set_field_back(info->fields[FLD_SAVE_PATH], A_UNDERLINE); @@ -548,7 +548,7 @@ save_win_new() form_opts_off(info->form, O_BS_OVERLOAD); // Set Default field values - char savepath[MAX_SETTING_LEN]; + char savepath[SETTING_MAX_LEN]; sprintf(savepath, "%s", setting_get_value(SETTING_SAVEPATH)); set_field_buffer(info->fields[FLD_SAVE_PATH], 0, savepath); diff --git a/src/ncurses/windows/settings_win.c b/src/ncurses/windows/settings_win.c index 0ae6428..ddb4633 100644 --- a/src/ncurses/windows/settings_win.c +++ b/src/ncurses/windows/settings_win.c @@ -324,7 +324,7 @@ settings_handle_key(Window *ui, int key) { int field_idx; SettingsWinEntry *entry; - enum setting_fmt sett_fmt = -1; + enum SettingFormat sett_fmt = -1; // Get panel information SettingsWinInfo *info = settings_info(ui); @@ -536,6 +536,11 @@ settings_win_new() field_opts_off(entry, O_STATIC); set_field_back(entry, A_UNDERLINE); break; + case SETTING_FMT_BOOLEAN: + entry = new_field(1, 12, line, 48, 0, 0); + field_opts_off(entry, O_EDIT); + set_field_type(entry, TYPE_ENUM, setting_valid_values(entries[j].setting_id), 0, 0); + break; case SETTING_FMT_ENUM: entry = new_field(1, 12, line, 48, 0, 0); field_opts_off(entry, O_EDIT); diff --git a/src/ncurses/windows/settings_win.h b/src/ncurses/windows/settings_win.h index 970c7d5..f7dad6f 100644 --- a/src/ncurses/windows/settings_win.h +++ b/src/ncurses/windows/settings_win.h @@ -149,7 +149,7 @@ struct _SettingsWinEntry { //! Field id in settings_info array enum SettingWinField field_id; //! Setting id of current entry - enum setting_id setting_id; + enum SettingId setting_id; //! Entry text const char *label; }; diff --git a/src/option.c b/src/option.c deleted file mode 100644 index 94a985d..0000000 --- a/src/option.c +++ /dev/null @@ -1,214 +0,0 @@ -/************************************************************************** - ** - ** sngrep - SIP Messages flow viewer - ** - ** Copyright (C) 2013-2018 Ivan Alonso (Kaian) - ** Copyright (C) 2013-2018 Irontec SL. All rights reserved. - ** - ** This program is free software: you can redistribute it and/or modify - ** it under the terms of the GNU General Public License as published by - ** the Free Software Foundation, either version 3 of the License, or - ** (at your option) any later version. - ** - ** This program is distributed in the hope that it will be useful, - ** but WITHOUT ANY WARRANTY; without even the implied warranty of - ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - ** GNU General Public License for more details. - ** - ** You should have received a copy of the GNU General Public License - ** along with this program. If not, see . - ** - ****************************************************************************/ -/** - * @file option.c - * @author Ivan Alonso [aka Kaian] - * - * @brief Source code of functions defined in option.h - * - */ -#include "config.h" -#include -#include -#include -#include -#include -#include "ncurses/keybinding.h" -#include "option.h" -#include "setting.h" -#include "timeval.h" - -/** - * @brief Configuration options array - * - * Contains all availabe options that can be optionured - * @todo make this dynamic - */ -option_opt_t options[1024]; -int optscnt = 0; - -int -init_options(int no_config) -{ - // Custom user conf file - GString *userconf = NULL; - char *rcfile; - char pwd[MAX_SETTING_LEN]; - - // Defualt savepath is current directory - if (getcwd(pwd, MAX_SETTING_LEN)) { - setting_set_value(SETTING_SAVEPATH, pwd); - } - - // Initialize settings - setting_set_value(SETTING_FILTER_METHODS, "REGISTER,INVITE,SUBSCRIBE,NOTIFY,OPTIONS,PUBLISH,MESSAGE,INFO,REFER,UPDATE"); - - // Add Call list column options - set_option_value("cl.column0", "index"); - set_option_value("cl.column1", "method"); - set_option_value("cl.column2", "sipfrom"); - set_option_value("cl.column3", "sipto"); - set_option_value("cl.column4", "msgcnt"); - set_option_value("cl.column5", "src"); - set_option_value("cl.column6", "dst"); - set_option_value("cl.column7", "state"); - - // Done if config file should not be read - if(no_config) { - return 0; - } - - // Read options from configuration files - read_options("/etc/sngreprc"); - read_options("/usr/local/etc/sngreprc"); - - // Get user configuration - if ((rcfile = getenv("SNGREPRC"))) { - read_options(rcfile); - } else if ((rcfile = getenv("HOME"))) { - userconf = g_string_new(rcfile); - g_string_append(userconf, "/.sngreprc"); - read_options(userconf->str); - g_string_free(userconf, TRUE); - } - - return 0; -} - -void -deinit_options() -{ - int i; - // Deallocate options memory - for (i = 0; i < optscnt; i++) { - g_free(options[i].opt); - g_free(options[i].value); - } -} - -int -read_options(const char *fname) -{ - FILE *fh; - char line[1024], type[20], option[50], value[50]; - int id; - - if (!(fh = fopen(fname, "rt"))) - return -1; - - while (fgets(line, 1024, fh) != NULL) { - // Check if this line is a commentary or empty line - if (!strlen(line) || *line == '#') - continue; - - // Get configuration option from setting line - if (sscanf(line, "%s %s %[^\t\n]", type, option, value) == 3) { - if (!strcasecmp(type, "set")) { - if ((id = setting_id(option)) >= 0) { - setting_set_value(id, value); - } else { - set_option_value(option, value); - } - } else if (!strcasecmp(type, "alias")) { - set_alias_value(option, value); - } else if (!strcasecmp(type, "bind")) { - key_bind_action(key_action_id(option), key_from_str(value)); - } else if (!strcasecmp(type, "unbind")) { - key_unbind_action(key_action_id(option), key_from_str(value)); - } - } - } - fclose(fh); - return 0; -} - -const char* -get_option_value(const char *opt) -{ - int i; - for (i = 0; i < optscnt; i++) { - if (!strcasecmp(opt, options[i].opt)) { - return options[i].value; - } - } - return NULL; -} - -int -get_option_int_value(const char *opt) -{ - const char *value; - if ((value = get_option_value(opt))) { - return atoi(value); - } - return -1; -} - -void -set_option_value(const char *opt, const char *value) -{ - if (!opt || !value) - return; - - int i; - if (!get_option_value(opt)) { - options[optscnt].type = COLUMN; - options[optscnt].opt = strdup(opt); - options[optscnt].value = strdup(value); - optscnt++; - } else { - for (i = 0; i < optscnt; i++) { - if (!strcasecmp(opt, options[i].opt)) { - g_free(options[i].value); - options[i].value = strdup(value); - } - } - } -} - -void -set_alias_value(const char *address, const char *alias) -{ - options[optscnt].type = ALIAS; - options[optscnt].opt = strdup(address); - options[optscnt].value = strdup(alias); - optscnt++; -} - -const char * -get_alias_value(const char *address) -{ - int i; - - if (!address) - return NULL; - - for (i = 0; i < optscnt; i++) { - if (options[i].type != ALIAS) - continue; - if (!strcmp(options[i].opt, address)) - return options[i].value; - } - - return address; -} - diff --git a/src/option.h b/src/option.h deleted file mode 100644 index 999367d..0000000 --- a/src/option.h +++ /dev/null @@ -1,161 +0,0 @@ -/************************************************************************** - ** - ** sngrep - SIP Messages flow viewer - ** - ** Copyright (C) 2013-2018 Ivan Alonso (Kaian) - ** Copyright (C) 2013-2018 Irontec SL. All rights reserved. - ** - ** This program is free software: you can redistribute it and/or modify - ** it under the terms of the GNU General Public License as published by - ** the Free Software Foundation, either version 3 of the License, or - ** (at your option) any later version. - ** - ** This program is distributed in the hope that it will be useful, - ** but WITHOUT ANY WARRANTY; without even the implied warranty of - ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - ** GNU General Public License for more details. - ** - ** You should have received a copy of the GNU General Public License - ** along with this program. If not, see . - ** - ****************************************************************************/ -/** - * @file option.h - * @author Ivan Alonso [aka Kaian] - * - * @brief Functions to manage application settings - * - * This file contains the functions to manage application settings and - * optionuration resource files. Configuration will be parsed in this order, - * from less to more priority, so the later will overwrite the previous. - * - * - Initialization - * - \@sysdir\@/sngreprc - * - $HOME/.sngreprc - * - $SNGREPRC - * - * This is a basic approach to configuration, but at least a minimun is required - * for those who can not see all the list columns or want to disable colours in - * every sngrep execution. - * - */ - -#ifndef __SNGREP_CONFIG_H -#define __SNGREP_CONFIG_H - -//! Shorter declarartion of config_option struct -typedef struct config_option option_opt_t; - -//! Option types -enum option_type { - COLUMN = 0, - ALIAS -}; - -/** - * @brief Configurable option structure - * - * sngrep is optionured by a group of attributes that can be - * modified using resource files. - */ -struct config_option { - //! Setting type - enum option_type type; - //! Name of attribute - char *opt; - //! Value of attribute - char *value; -}; - -/** - * @brief Initialize all program options - * - * This function will give all available settings an initial value. - * This values can be overriden using resources files, either from system dir - * or user home dir. - * - * @param no_config Do not load config file if set to 1 - * @return 0 in all cases - */ -int -init_options(int no_config); - -/** - * @brief Deallocate options memory - * - * Deallocate memory used for program configurations - */ -void -deinit_options(); - -/** - * @brief Read optionuration directives from file - * - * This funtion will parse passed filenames searching for configuration - * directives of sngrep. See documentation for a list of available - * directives and attributes - * - * @param fname Full path configuration file name - * @return 0 in case of parse success, -1 otherwise - */ -int -read_options(const char *fname); - -/** - * @brief Get settings option value (string) - * - * Used in all the program to access the optionurable options of sngrep - * Use this function instead of accessing optionuration array. - * - * @param opt Name of optionurable option - * @return configuration option value or NULL if not found - */ -const char* -get_option_value(const char *opt); - -/** - * @brief Get settings option value (int) - * - * Basically the same as get_option_value converting the result to - * integer. - * Use this function instead of accessing configuration array. - * - * @todo -1 is an error! - * - * @param opt Name of optionurable option - * @return option numeric value or -1 in case of error - */ -int -get_option_int_value(const char *opt); - -/** - * @brief Sets a settings option value - * - * Basic setter for 'set' directive attributes - * - * @param opt Name of configuration option - * @param value Value of configuration option - */ -void -set_option_value(const char *opt, const char *value); - -/** - * @brief Sets an alias for a given address - * - * @param address IP Address - * @param string representing the alias - */ -void -set_alias_value(const char *address, const char *alias); - -/** - * @brief Get alias for a given address (string) - * - * @param address IP Address - * @return configured alias or address if not alias found - */ -const char * -get_alias_value(const char *address); - - -#endif diff --git a/src/setting.c b/src/setting.c index b6a0b2d..527c146 100644 --- a/src/setting.c +++ b/src/setting.c @@ -28,155 +28,159 @@ */ #include "config.h" #include +#include #include #include +#include "ncurses/keybinding.h" +#include "glib-utils.h" #include "setting.h" #include "timeval.h" +/** + * @brief Storage settings + * + * This struct contains all the configurable options and can be updated + * from resource files. + * + * - Settings + * - Alias + * - Call List columns + */ +static SettingStorage *storage = NULL; -//! Available configurable settings -setting_t settings[SETTING_COUNT] = { - { SETTING_BACKGROUND, "background", SETTING_FMT_ENUM, "dark", SETTING_ENUM_BACKGROUND }, - { SETTING_COLORMODE, "colormode", SETTING_FMT_ENUM, "request", SETTING_ENUM_COLORMODE }, - { SETTING_SYNTAX, "syntax", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_SYNTAX_TAG, "syntax.tag", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_SYNTAX_BRANCH, "syntax.branch", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_ALTKEY_HINT, "hintkeyalt", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_EXITPROMPT, "exitprompt", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_CAPTURE_LIMIT, "capture.limit", SETTING_FMT_NUMBER, "20000", NULL }, - { SETTING_CAPTURE_DEVICE, "capture.device", SETTING_FMT_STRING, "any", NULL }, - { SETTING_CAPTURE_OUTFILE, "capture.outfile", SETTING_FMT_STRING, "", NULL }, -#ifdef WITH_SSL - { SETTING_CAPTURE_KEYFILE, "capture.keyfile", SETTING_FMT_STRING, "", NULL }, - { SETTING_CAPTURE_TLSSERVER, "capture.tlsserver", SETTING_FMT_STRING, "", NULL }, -#endif - { SETTING_CAPTURE_RTP, "capture.rtp", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_CAPTURE_STORAGE, "capture.storage", SETTING_FMT_ENUM, "memory", SETTING_ENUM_STORAGE }, - { SETTING_CAPTURE_ROTATE, "capture.rotate", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_SIP_NOINCOMPLETE, "sip.noincomplete", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_SIP_HEADER_X_CID, "sip.xcid", SETTING_FMT_STRING, "X-Call-ID|X-CID", NULL }, - { SETTING_SIP_CALLS, "sip.calls", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_SAVEPATH, "savepath", SETTING_FMT_STRING, "", NULL }, - { SETTING_DISPLAY_ALIAS, "displayalias", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_CL_SCROLLSTEP, "cl.scrollstep", SETTING_FMT_NUMBER, "4", NULL }, - { SETTING_CL_COLORATTR, "cl.colorattr", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_CL_AUTOSCROLL, "cl.autoscroll", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_CL_SORTFIELD, "cl.sortfield", SETTING_FMT_STRING, "index", NULL }, - { SETTING_CL_SORTORDER, "cl.sortorder", SETTING_FMT_STRING, "asc", NULL }, - { SETTING_CF_FORCERAW, "cf.forceraw", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_CF_RAWMINWIDTH, "cf.rawminwidth", SETTING_FMT_NUMBER, "40", NULL }, - { SETTING_CF_RAWFIXEDWIDTH, "cf.rawfixedwidth", SETTING_FMT_NUMBER, "", NULL }, - { SETTING_CF_SPLITCALLID, "cf.splitcallid", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_CF_HIGHTLIGHT, "cf.highlight", SETTING_FMT_ENUM, "bold", SETTING_ENUM_HIGHLIGHT }, - { SETTING_CF_SCROLLSTEP, "cf.scrollstep", SETTING_FMT_NUMBER, "4", NULL }, - { SETTING_CF_LOCALHIGHLIGHT, "cf.localhighlight", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_CF_SDP_INFO, "cf.sdpinfo", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_SDP_INFO }, - { SETTING_CF_MEDIA, "cf.media", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_MEDIA }, - { SETTING_CF_ONLYMEDIA, "cf.onlymedia", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_CF_DELTA, "cf.deltatime", SETTING_FMT_ENUM, SETTING_ON, SETTING_ENUM_ONOFF }, - { SETTING_CR_SCROLLSTEP, "cr.scrollstep", SETTING_FMT_NUMBER, "10", NULL }, - { SETTING_CR_NON_ASCII, "cr.nonascii", SETTING_FMT_STRING, ".", NULL }, - { SETTING_FILTER_PAYLOAD, "filter.payload", SETTING_FMT_STRING, "", NULL }, - { SETTING_FILTER_METHODS, "filter.methods", SETTING_FMT_STRING, "", NULL }, -#ifdef USE_HEP - { SETTING_HEP_SEND, "eep.send", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_HEP_SEND_VER, "eep.send.version", SETTING_FMT_ENUM, "3", SETTING_ENUM_HEPVERSION }, - { SETTING_HEP_SEND_ADDR, "eep.send.address", SETTING_FMT_STRING, "127.0.0.1", NULL }, - { SETTING_HEP_SEND_PORT, "eep.send.port", SETTING_FMT_NUMBER, "9060", NULL }, - { SETTING_HEP_SEND_PASS, "eep.send.pass", SETTING_FMT_STRING, "", NULL }, - { SETTING_HEP_SEND_ID, "eep.send.id", SETTING_FMT_NUMBER, "2002", NULL }, - { SETTING_HEP_LISTEN, "eep.listen", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, - { SETTING_HEP_LISTEN_VER, "eep.listen.version", SETTING_FMT_ENUM, "3", SETTING_ENUM_HEPVERSION }, - { SETTING_HEP_LISTEN_ADDR, "eep.listen.address", SETTING_FMT_STRING, "0.0.0.0", NULL }, - { SETTING_HEP_LISTEN_PORT, "eep.listen.port", SETTING_FMT_NUMBER, "9060", NULL }, - { SETTING_HEP_LISTEN_PASS, "eep.listen.pass", SETTING_FMT_STRING, "", NULL }, - { SETTING_HEP_LISTEN_UUID, "eep.listen.uuid", SETTING_FMT_ENUM, SETTING_OFF, SETTING_ENUM_ONOFF }, -#endif -}; - -setting_t * -setting_by_id(int id) +/** + * @brief Create a new number type setting + */ +static Setting * +setting_number_new(const gchar *name, const gchar *value) { - int i; - for (i = 0; i < SETTING_COUNT; i++) { - if ((guint) id == settings[i].id) - return &settings[i]; + Setting *setting = g_malloc0(sizeof(Setting)); + setting->name = name; + setting->fmt = SETTING_FMT_NUMBER; + strncpy(setting->value, value, SETTING_MAX_LEN); + return setting; +} + +/** + * @brief Create a new string type setting + */ +static Setting * +setting_string_new(const gchar *name, const gchar *value) +{ + Setting *setting = g_malloc0(sizeof(Setting)); + setting->name = name; + setting->fmt = SETTING_FMT_STRING; + strncpy(setting->value, value, SETTING_MAX_LEN); + return setting; +} + +/** + * @brief Create a new boolean type setting + */ +static Setting * +setting_bool_new(const gchar *name, const gchar *value) +{ + Setting *setting = g_malloc0(sizeof(Setting)); + setting->name = name; + setting->fmt = SETTING_FMT_BOOLEAN; + strncpy(setting->value, value, SETTING_MAX_LEN); + setting->valuelist = g_strsplit("on,off", ",", -1); + return setting; +} + +/** + * @brief Create a new enum type setting + */ +static Setting * +setting_enum_new(const gchar *name, const gchar *value, const gchar *valuelist) +{ + Setting *setting = g_malloc0(sizeof(Setting)); + setting->name = name; + setting->fmt = SETTING_FMT_ENUM; + strncpy(setting->value, value, SETTING_MAX_LEN); + setting->valuelist = g_strsplit(valuelist, ",", -1); + return setting; +} + + +Setting * +setting_by_id(enum SettingId id) +{ + return g_ptr_array_index(storage->settings, id); +} + +Setting * +setting_by_name(const gchar *name) +{ + for (guint i = 0; i < g_ptr_array_len(storage->settings); i++) { + Setting *setting = g_ptr_array_index(storage->settings, i); + if (g_strcmp0(setting->name, name) == 0) { + return setting; + } } return NULL; } -setting_t * -setting_by_name(const char *name) +enum SettingId +setting_id(const gchar *name) { - int i; - for (i = 0; i < SETTING_COUNT; i++) { - if (!strcmp(name, settings[i].name)) - return &settings[i]; - } - return NULL; + const Setting *sett = setting_by_name(name); + return (sett) ? g_ptr_array_data_index(storage->settings, sett): SETTING_UNKNOWN; } -int -setting_id(const char *name) +const gchar * +setting_name(enum SettingId id) { - const setting_t *sett = setting_by_name(name); - return (sett) ? (int) sett->id : -1; -} - -const char * -setting_name(int id) -{ - const setting_t *sett = setting_by_id(id); + const Setting *sett = setting_by_id(id); return (sett) ? sett->name : NULL; } int -setting_format(int id) +setting_format(enum SettingId id) { - const setting_t *sett = setting_by_id(id); + const Setting *sett = setting_by_id(id); return (sett) ? (int) sett->fmt : -1; } const char ** -setting_valid_values(int id) +setting_valid_values(enum SettingId id) { - const setting_t *sett = setting_by_id(id); + const Setting *sett = setting_by_id(id); return (sett) ? sett->valuelist : NULL; } const char * -setting_get_value(int id) +setting_get_value(enum SettingId id) { - const setting_t *sett = setting_by_id(id); + const Setting *sett = setting_by_id(id); return (sett && strlen(sett->value)) ? sett->value : NULL; } int -setting_get_intvalue(int id) +setting_get_intvalue(enum SettingId id) { - const setting_t *sett = setting_by_id(id); + const Setting *sett = setting_by_id(id); return (sett && strlen(sett->value)) ? atoi(sett->value) : -1; } void -setting_set_value(int id, const char *value) +setting_set_value(enum SettingId id, const char *value) { - setting_t *sett = setting_by_id(id); - if (sett) { - memset(sett->value, 0, sizeof(sett->value)); - if (value) { - if (strlen(value) < MAX_SETTING_LEN) { - strcpy(sett->value, value); - } else { - fprintf(stderr, "Setting value %s for %s is too long\n", sett->value, sett->name); - exit(1); - } + Setting *sett = setting_by_id(id); + g_return_if_fail(sett != NULL); + memset(sett->value, 0, sizeof(sett->value)); + if (value) { + if (strlen(value) < SETTING_MAX_LEN) { + strcpy(sett->value, value); + } else { + fprintf(stderr, "Setting value %s for %s is too long\n", sett->value, sett->name); + exit(1); } } } void -setting_set_intvalue(int id, int value) +setting_set_intvalue(enum SettingId id, int value) { char strvalue[80]; sprintf(strvalue, "%d", value); @@ -184,23 +188,23 @@ setting_set_intvalue(int id, int value) } int -setting_enabled(int id) +setting_enabled(enum SettingId id) { return setting_has_value(id, "on") || setting_has_value(id, "yes"); } int -setting_disabled(int id) +setting_disabled(enum SettingId id) { return setting_has_value(id, "off") || setting_has_value(id, "no"); } int -setting_has_value(int id, const char *value) +setting_has_value(enum SettingId id, const char *value) { - setting_t *sett = setting_by_id(id); + Setting *sett = setting_by_id(id); if (sett) { return !strcmp(sett->value, value); } @@ -209,27 +213,30 @@ setting_has_value(int id, const char *value) } void -setting_toggle(int id) +setting_toggle(enum SettingId id) { - setting_t *sett = setting_by_id(id); + Setting *sett = setting_by_id(id); if (sett) { - if (sett->fmt == SETTING_FMT_STRING) - return; - if (sett->fmt == SETTING_FMT_NUMBER) - return; - if (sett->fmt == SETTING_FMT_ENUM) { - setting_set_value(id, setting_enum_next(id, sett->value)); + switch(sett->fmt) { + case SETTING_FMT_BOOLEAN: + (setting_enabled(id)) ? setting_set_value(id, SETTING_OFF) : setting_set_value(id, SETTING_ON); + break; + case SETTING_FMT_ENUM: + setting_set_value(id, setting_enum_next(id, sett->value)); + case SETTING_FMT_STRING: break; + case SETTING_FMT_NUMBER: break; + default: break; } } } const char * -setting_enum_next(int id, const char *value) +setting_enum_next(enum SettingId id, const char *value) { int i; const char *vnext; - setting_t *sett; + Setting *sett; if (!(sett = setting_by_id(id))) return NULL; @@ -256,12 +263,335 @@ setting_enum_next(int id, const char *value) return NULL; } +gint +setting_column_pos(enum AttributeId id) +{ + const gchar *sett_name = attr_name(id); + g_return_val_if_fail(sett_name != NULL, -1); + + gchar *sett_text = g_strdup_printf("cl.column.%s.pos", sett_name); + g_return_val_if_fail(sett_text != NULL, -1); + + gint sett_id = setting_id(sett_text); + g_free(sett_text); + g_return_val_if_fail(sett_id != SETTING_UNKNOWN, -1); + + return setting_get_intvalue(sett_id); +} + +gint +setting_column_width(enum AttributeId id) +{ + const gchar *sett_name = attr_name(id); + g_return_val_if_fail(sett_name != NULL, -1); + + gchar *sett_text = g_strdup_printf("cl.column.%s.width", sett_name); + g_return_val_if_fail(sett_text != NULL, -1); + + gint sett_id = setting_id(sett_text); + g_free(sett_text); + g_return_val_if_fail(setting_name != NULL, -1); + + return setting_get_intvalue(sett_id); +} + +/** + * @brief Sets an alias for a given address + * + * @param address IP Address + * @param string representing the alias + */ +static void +setting_add_alias(const gchar *address, const gchar *alias) +{ + SettingAlias *setting = g_malloc0(sizeof(SettingAlias)); + setting->address = address; + setting->alias = alias; + storage->alias = g_list_append(storage->alias, setting); +} + +const gchar * +setting_get_alias(const gchar *address) +{ + g_return_val_if_fail(address != NULL, NULL); + + for (GList *l = storage->alias; l != NULL; l = l->next) { + SettingAlias *alias = l->data; + if (g_strcmp0(alias->address, address) == 0) { + return alias->alias; + } + } + + return NULL; +} + +int +setting_read_file(const gchar *fname) +{ + FILE *fh; + char line[1024], type[20], option[50], value[50]; + + if (!(fh = fopen(fname, "rt"))) + return -1; + + while (fgets(line, 1024, fh) != NULL) { + // Check if this line is a commentary or empty line + if (!strlen(line) || *line == '#') + continue; + + // Get configuration option from setting line + if (sscanf(line, "%s %s %[^\t\n]", type, option, value) == 3) { + if (!strcasecmp(type, "set")) { + setting_set_value(setting_id(option), value); + } else if (!strcasecmp(type, "alias")) { + setting_add_alias(option, value); + } else if (!strcasecmp(type, "bind")) { + key_bind_action(key_action_id(option), key_from_str(value)); + } else if (!strcasecmp(type, "unbind")) { + key_unbind_action(key_action_id(option), key_from_str(value)); + } + } + } + fclose(fh); + return 0; +} + +int +settings_init(int no_config) +{ + // Custom user conf file + GString *userconf = NULL; + char *rcfile; + + // Allocate memory for settings storage + storage = g_malloc0(sizeof(SettingStorage)); + storage->settings = g_ptr_array_new_with_free_func(g_free); + g_ptr_array_set_size(storage->settings, SETTING_COUNT); + + // Default settings values + g_ptr_array_set(storage->settings, SETTING_BACKGROUND, + setting_enum_new("background", "dark", "dark,default")); + g_ptr_array_set(storage->settings, SETTING_COLORMODE, + setting_enum_new("colormode", "request", "request,cseq,callid")); + g_ptr_array_set(storage->settings, SETTING_SYNTAX, + setting_bool_new("syntax", SETTING_ON)); + g_ptr_array_set(storage->settings, SETTING_SYNTAX_TAG, + setting_bool_new("syntax.tag", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_SYNTAX_BRANCH, + setting_bool_new("syntax.tag", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_ALTKEY_HINT, + setting_bool_new("syntax.branch", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_SYNTAX_TAG, + setting_bool_new("hintkeyalt", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_EXITPROMPT, + setting_bool_new("exitprompt", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CAPTURE_LIMIT, + setting_number_new("capture.limit", "20000")); + g_ptr_array_set(storage->settings, SETTING_CAPTURE_DEVICE, + setting_string_new("capture.device", "any")); + g_ptr_array_set(storage->settings, SETTING_CAPTURE_OUTFILE, + setting_string_new("capture.outfile", "")); +#ifdef WITH_SSL + g_ptr_array_set(storage->settings, SETTING_CAPTURE_KEYFILE, + setting_string_new("capture.keyfile", "")); + g_ptr_array_set(storage->settings, SETTING_CAPTURE_TLSSERVER, + setting_string_new("capture.tlsserver", "")); +#endif + g_ptr_array_set(storage->settings, SETTING_CAPTURE_RTP, + setting_bool_new("capture.rtp", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CAPTURE_STORAGE, + setting_enum_new("capture.storage", "memory", "none,memory")); + g_ptr_array_set(storage->settings, SETTING_CAPTURE_ROTATE, + setting_bool_new("capture.rotate", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_SIP_NOINCOMPLETE, + setting_bool_new("sip.noincomplete", SETTING_ON)); + g_ptr_array_set(storage->settings, SETTING_SIP_HEADER_X_CID, + setting_string_new("sip.xcid", "X-Call-ID|X-CID")); + g_ptr_array_set(storage->settings, SETTING_SIP_CALLS, + setting_bool_new("sip.calls", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_SAVEPATH, + setting_string_new("savepath", g_get_current_dir())); + g_ptr_array_set(storage->settings, SETTING_DISPLAY_ALIAS, + setting_bool_new("displayalias", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CL_SCROLLSTEP, + setting_number_new("cl.scrollstep", "4")); + g_ptr_array_set(storage->settings, SETTING_CL_COLORATTR, + setting_bool_new("cl.colorattr", SETTING_ON)); + g_ptr_array_set(storage->settings, SETTING_CL_AUTOSCROLL, + setting_bool_new("cl.autoscroll", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CL_SORTFIELD, + setting_string_new("cl.sortfield", attr_name(ATTR_CALLINDEX))); + g_ptr_array_set(storage->settings, SETTING_CL_SORTORDER, + setting_string_new("cl.sortorder", "asc")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_INDEX_POS, + setting_number_new("cl.column.index.pos", "0")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_INDEX_WIDTH, + setting_number_new("cl.column.index.width", "4")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPFROM_POS, + setting_number_new("cl.column.sipfrom.pos", "2")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPFROM_WIDTH, + setting_number_new("cl.column.sipfrom.width", "25")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPFROMUSER_POS, + setting_number_new("cl.column.sipfromuser.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPFROMUSER_WIDTH, + setting_number_new("cl.column.sipfromuser.width", "20")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPTO_POS, + setting_number_new("cl.column.sipto.pos", "3")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPTO_WIDTH, + setting_number_new("cl.column.sipto.width", "25")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPTOUSER_POS, + setting_number_new("cl.column.siptouser.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SIPTOUSER_WIDTH, + setting_number_new("cl.column.siptouser.width", "20")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SRC_POS, + setting_number_new("cl.column.src.pos", "5")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_SRC_WIDTH, + setting_number_new("cl.column.src.width", "22")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_DST_POS, + setting_number_new("cl.column.dst.pos", "6")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_DST_WIDTH, + setting_number_new("cl.column.dst.width", "22")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_CALLID_POS, + setting_number_new("cl.column.callid.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_CALLID_WIDTH, + setting_number_new("cl.column.callid.width", "50")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_XCALLID_POS, + setting_number_new("cl.column.xcallid.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_XCALLID_WIDTH, + setting_number_new("cl.column.xcallid.width", "50")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_DATE_POS, + setting_number_new("cl.column.date.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_DATE_WIDTH, + setting_number_new("cl.column.date.width", "10")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_TIME_POS, + setting_number_new("cl.column.time.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_TIME_WIDTH, + setting_number_new("cl.column.time.width", "8")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_METHOD_POS, + setting_number_new("cl.column.method.pos", "1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_METHOD_WIDTH, + setting_number_new("cl.column.method.width", "10")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_TRANSPORT_POS, + setting_number_new("cl.column.transport.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_TRANSPORT_WIDTH, + setting_number_new("cl.column.transport.width", "3")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_MSGCNT_POS, + setting_number_new("cl.column.msgcnt.pos", "4")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_MSGCNT_WIDTH, + setting_number_new("cl.column.msgcnt.width", "5")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_CALLSTATE_POS, + setting_number_new("cl.column.state.pos", "7")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_CALLSTATE_WIDTH, + setting_number_new("cl.column.state.width", "10")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_CONVDUR_POS, + setting_number_new("cl.column.convdur.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_CONVDUR_WIDTH, + setting_number_new("cl.column.convdur.width", "7")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_TOTALDUR_POS, + setting_number_new("cl.column.totaldur.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_TOTALDUR_WIDTH, + setting_number_new("cl.column.totaldur.width", "8")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_REASON_TXT_POS, + setting_number_new("cl.column.reason.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_REASON_TXT_WIDTH, + setting_number_new("cl.column.reason.width", "25")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_WARNING_POS, + setting_number_new("cl.column.warning.pos", "-1")); + g_ptr_array_set(storage->settings, SETTING_CL_COL_WARNING_WIDTH, + setting_number_new("cl.column.warning.width", "4")); + g_ptr_array_set(storage->settings, SETTING_CF_FORCERAW, + setting_bool_new("cf.forceraw", SETTING_ON)); + g_ptr_array_set(storage->settings, SETTING_CF_RAWMINWIDTH, + setting_number_new("cf.rawminwidth", "40")); + g_ptr_array_set(storage->settings, SETTING_CF_RAWFIXEDWIDTH, + setting_number_new("cf.rawfixedwidth", "")); + g_ptr_array_set(storage->settings, SETTING_CF_SPLITCALLID, + setting_bool_new("cf.splitcallid", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CF_HIGHTLIGHT, + setting_enum_new("cf.highlight", "bold", "bold,reverse,reversebold")); + g_ptr_array_set(storage->settings, SETTING_CF_SCROLLSTEP, + setting_number_new("cf.scrollstep", "4")); + g_ptr_array_set(storage->settings, SETTING_CF_LOCALHIGHLIGHT, + setting_bool_new("cf.localhighlight", SETTING_ON)); + g_ptr_array_set(storage->settings, SETTING_CF_SDP_INFO, + setting_enum_new("cf.sdpinfo", SETTING_OFF, "off,first,full,compressed")); + g_ptr_array_set(storage->settings, SETTING_CF_MEDIA, + setting_bool_new("cf.media", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CF_ONLYMEDIA, + setting_bool_new("cf.onlymedia", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_CF_DELTA, + setting_bool_new("cf.deltatime", SETTING_ON)); + g_ptr_array_set(storage->settings, SETTING_CR_SCROLLSTEP, + setting_number_new("cr.scrollstep", "10")); + g_ptr_array_set(storage->settings, SETTING_CR_NON_ASCII, + setting_string_new("cr.nonascii", ".")); + g_ptr_array_set(storage->settings, SETTING_FILTER_PAYLOAD, + setting_string_new("filter.payload", "")); + g_ptr_array_set(storage->settings, SETTING_FILTER_METHODS, + setting_string_new("filter.methods", + "REGISTER,INVITE,SUBSCRIBE,NOTIFY,OPTIONS,PUBLISH,MESSAGE,INFO,REFER,UPDATE")); +#ifdef USE_HEP + g_ptr_array_set(storage->settings, SETTING_HEP_SEND, + setting_bool_new("eep.send", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_HEP_SEND_VER, + setting_number_new("eep.send.version", "3")); + g_ptr_array_set(storage->settings, SETTING_HEP_SEND_ADDR, + setting_string_new("eep.send.address", "127.0.0.1")); + g_ptr_array_set(storage->settings, SETTING_HEP_SEND_PORT, + setting_number_new("eep.send.port", "9060")); + g_ptr_array_set(storage->settings, SETTING_HEP_SEND_PASS, + setting_string_new("eep.send.pass", "")); + g_ptr_array_set(storage->settings, SETTING_HEP_SEND_ID, + setting_number_new("eep.send.id", "2000")); + g_ptr_array_set(storage->settings, SETTING_HEP_LISTEN, + setting_bool_new("eep.listen", SETTING_OFF)); + g_ptr_array_set(storage->settings, SETTING_HEP_LISTEN_VER, + setting_string_new("eep.listen.version", "3")); + g_ptr_array_set(storage->settings, SETTING_HEP_LISTEN_ADDR, + setting_string_new("eep.listen.address", "0.0.0.0")); + g_ptr_array_set(storage->settings, SETTING_HEP_LISTEN_PORT, + setting_number_new("eep.listen.port", "9060")); + g_ptr_array_set(storage->settings, SETTING_HEP_LISTEN_PASS, + setting_string_new("eep.listen.pass", "")); + g_ptr_array_set(storage->settings, SETTING_HEP_LISTEN_UUID, + setting_bool_new("eep.listen.uuid", SETTING_OFF)); +#endif + + // Done if config file should not be read + if(no_config) { + return 0; + } + + // Read options from configuration files + setting_read_file("/etc/sngreprc"); + setting_read_file("/usr/local/etc/sngreprc"); + + // Get user configuration + if ((rcfile = getenv("SNGREPRC"))) { + setting_read_file(rcfile); + } else if ((rcfile = getenv("HOME"))) { + userconf = g_string_new(rcfile); + g_string_append(userconf, "/.sngreprc"); + setting_read_file(userconf->str); + g_string_free(userconf, TRUE); + } + + return 0; +} + +void +settings_deinit() +{ + g_ptr_array_free(storage->settings, TRUE); + g_list_free(storage->alias); + g_free(storage); +} + void settings_dump() { - int i; - for (i = 1; i < SETTING_COUNT; i++) { - printf("SettingId: %d\t SettingName: %-20s Value: %s\n", i, + for (guint i = 1; i < SETTING_COUNT; i++) { + printf("SettingId: %d\t SettingName: %-30s Value: %s\n", i, setting_name(i), setting_get_value(i)); } diff --git a/src/setting.h b/src/setting.h index 9480062..1cf10ed 100644 --- a/src/setting.h +++ b/src/setting.h @@ -42,36 +42,24 @@ #ifndef __SNGREP_SETTING_H #define __SNGREP_SETTING_H -//! Max setting value -#define MAX_SETTING_LEN 1024 +#include +#include "attribute.h" -//! Max extra length needed for "/.sngreprc.old" -#define RCFILE_EXTRA_LEN 16 +//! Max setting value +#define SETTING_MAX_LEN 1024 //! Shorter declarartion of setting_option struct -typedef struct setting_option setting_t; - -//! Generic setting formats -#define SETTING_ENUM_ONOFF (const char *[]){ "on", "off", NULL } -#define SETTING_ENUM_YESNO (const char *[]){ "yes", "no", NULL } -#define SETTING_ENUM_BACKGROUND (const char *[]){ "dark" , "default", NULL } -#define SETTING_ENUM_COLORMODE (const char *[]){ "request", "cseq", "callid", NULL } -#define SETTING_ENUM_HIGHLIGHT (const char *[]){ "bold", "reverse", "reversebold", NULL } -#define SETTING_ENUM_SDP_INFO (const char *[]){ "off", "first", "full", "compressed", NULL} -#define SETTING_ENUM_STORAGE (const char *[]){ "none", "memory", NULL } -#define SETTING_ENUM_HEPVERSION (const char *[]){ "2", "3", NULL } -#define SETTING_ENUM_MEDIA (const char *[]){ "off", "on", "active", NULL } +typedef struct _Setting Setting; +typedef struct _SettingStorage SettingStorage; +typedef struct _SettingAlias SettingAlias; //! Other useful defines #define SETTING_ON "on" #define SETTING_OFF "off" -#define SETTING_YES "yes" -#define SETTING_NO "no" -#define SETTING_ACTIVE "active" - //! Available setting Options -enum setting_id { +enum SettingId { + SETTING_UNKNOWN = -1, SETTING_BACKGROUND = 0, SETTING_COLORMODE, SETTING_SYNTAX, @@ -99,6 +87,44 @@ enum setting_id { SETTING_CL_AUTOSCROLL, SETTING_CL_SORTFIELD, SETTING_CL_SORTORDER, + SETTING_CL_COL_INDEX_POS, + SETTING_CL_COL_INDEX_WIDTH, + SETTING_CL_COL_SIPFROM_POS, + SETTING_CL_COL_SIPFROM_WIDTH, + SETTING_CL_COL_SIPFROMUSER_POS, + SETTING_CL_COL_SIPFROMUSER_WIDTH, + SETTING_CL_COL_SIPTO_POS, + SETTING_CL_COL_SIPTO_WIDTH, + SETTING_CL_COL_SIPTOUSER_POS, + SETTING_CL_COL_SIPTOUSER_WIDTH, + SETTING_CL_COL_SRC_POS, + SETTING_CL_COL_SRC_WIDTH, + SETTING_CL_COL_DST_POS, + SETTING_CL_COL_DST_WIDTH, + SETTING_CL_COL_CALLID_POS, + SETTING_CL_COL_CALLID_WIDTH, + SETTING_CL_COL_XCALLID_POS, + SETTING_CL_COL_XCALLID_WIDTH, + SETTING_CL_COL_DATE_POS, + SETTING_CL_COL_DATE_WIDTH, + SETTING_CL_COL_TIME_POS, + SETTING_CL_COL_TIME_WIDTH, + SETTING_CL_COL_METHOD_POS, + SETTING_CL_COL_METHOD_WIDTH, + SETTING_CL_COL_TRANSPORT_POS, + SETTING_CL_COL_TRANSPORT_WIDTH, + SETTING_CL_COL_MSGCNT_POS, + SETTING_CL_COL_MSGCNT_WIDTH, + SETTING_CL_COL_CALLSTATE_POS, + SETTING_CL_COL_CALLSTATE_WIDTH, + SETTING_CL_COL_CONVDUR_POS, + SETTING_CL_COL_CONVDUR_WIDTH, + SETTING_CL_COL_TOTALDUR_POS, + SETTING_CL_COL_TOTALDUR_WIDTH, + SETTING_CL_COL_REASON_TXT_POS, + SETTING_CL_COL_REASON_TXT_WIDTH, + SETTING_CL_COL_WARNING_POS, + SETTING_CL_COL_WARNING_WIDTH, SETTING_CF_FORCERAW, SETTING_CF_RAWMINWIDTH, SETTING_CF_RAWFIXEDWIDTH, @@ -132,8 +158,9 @@ enum setting_id { }; //! Available setting formats -enum setting_fmt { +enum SettingFormat { SETTING_FMT_STRING = 0, + SETTING_FMT_BOOLEAN, SETTING_FMT_NUMBER, SETTING_FMT_ENUM, }; @@ -141,23 +168,39 @@ enum setting_fmt { /** * @brief Configurable Setting structure */ -struct setting_option { - //! Setting id - enum setting_id id; +struct _Setting { //! Setting name - const char *name; + const gchar *name; //! Setting format - enum setting_fmt fmt; + enum SettingFormat fmt; //! Value of the setting - char value[MAX_SETTING_LEN]; - //! Compa separated valid values - const char **valuelist; + char value[SETTING_MAX_LEN]; + //! Comma separated valid values + gchar **valuelist; }; -setting_t * -setting_by_id(int id); +/** + * @brief Alias setting structure + */ +struct _SettingAlias { + //! Original address value + const gchar *address; + //! Alias name + const gchar *alias; -setting_t * +}; + +struct _SettingStorage { + //! Array of settings + GPtrArray *settings; + //! List of configured IP address aliases + GList *alias; +}; + +Setting * +setting_by_id(enum SettingId id); + +Setting * setting_by_name(const char *name); /** @@ -166,7 +209,7 @@ setting_by_name(const char *name); * @param name String representing configurable setting * @return setting id or -1 if setting is not found */ -int +enum SettingId setting_id(const char *name); /** @@ -176,40 +219,95 @@ setting_id(const char *name); * @return string representation of setting or NULL */ const char * -setting_name(int id); +setting_name(enum SettingId id); int -setting_format(int id); +setting_format(enum SettingId id); const char ** -setting_valid_values(int id); +setting_valid_values(enum SettingId id); const char* -setting_get_value(int id); +setting_get_value(enum SettingId id); int -setting_get_intvalue(int id); +setting_get_intvalue(enum SettingId id); void -setting_set_value(int id, const char *value); +setting_set_value(enum SettingId id, const char *value); void -setting_set_intvalue(int id, int value); +setting_set_intvalue(enum SettingId id, int value); int -setting_enabled(int id); +setting_enabled(enum SettingId id); int -setting_disabled(int id); +setting_disabled(enum SettingId id); int -setting_has_value(int id, const char *value); +setting_has_value(enum SettingId id, const char *value); void -setting_toggle(int id); +setting_toggle(enum SettingId id); const char * -setting_enum_next(int id, const char *value); +setting_enum_next(enum SettingId id, const char *value); + +gint +setting_column_pos(enum AttributeId id); + +/** + * @brief Get Attribute column display width + * + * @param id Attribute id + * @return configured column width + */ +gint +setting_column_width(enum AttributeId id); + +/** + * @brief Get alias for a given address (string) + * + * @param address IP Address + * @return configured alias or address if not alias found + */ +const gchar * +setting_get_alias(const gchar *address); + +/** + * @brief Read optionuration directives from file + * + * This funtion will parse passed filenames searching for configuration + * directives of sngrep. See documentation for a list of available + * directives and attributes + * + * @param fname Full path configuration file name + * @return 0 in case of parse success, -1 otherwise + */ +int +setting_read_file(const gchar *fname); + +/** + * @brief Initialize all program options + * + * This function will give all available settings an initial value. + * This values can be overriden using resources files, either from system dir + * or user home dir. + * + * @param no_config Do not load config file if set to 1 + * @return 0 in all cases + */ +int +settings_init(int no_config); + +/** + * @brief Deallocate options memory + * + * Deallocate memory used for program configurations + */ +void +settings_deinit(); /** * @brief Dump configuration settings