diff options
Diffstat (limited to 'cli/src/utils.c')
| -rw-r--r-- | cli/src/utils.c | 1128 |
1 files changed, 0 insertions, 1128 deletions
diff --git a/cli/src/utils.c b/cli/src/utils.c deleted file mode 100644 index 9b513f5a..00000000 --- a/cli/src/utils.c +++ /dev/null @@ -1,1128 +0,0 @@ -/* nmcli - command-line tool to control NetworkManager - * - * 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 2 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, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2010 - 2014 Red Hat, Inc. - */ - -/* Generated configuration file */ -#include "config.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <glib.h> -#include <glib/gi18n.h> -#include <dbus/dbus-glib-bindings.h> - -#include "utils.h" - -int -matches (const char *cmd, const char *pattern) -{ - size_t len = strlen (cmd); - if (!len || len > strlen (pattern)) - return -1; - return memcmp (pattern, cmd, len); -} - -int -next_arg (int *argc, char ***argv) -{ - int arg_num = *argc; - - if (arg_num > 0) { - (*argc)--; - (*argv)++; - } - if (arg_num <= 1) - return -1; - - return 0; -} - -gboolean -nmc_arg_is_help (const char *arg) -{ - if (!arg) - return FALSE; - if ( matches (arg, "help") == 0 - || (g_str_has_prefix (arg, "-") && matches (arg+1, "help") == 0) - || (g_str_has_prefix (arg, "--") && matches (arg+2, "help") == 0)) { - return TRUE; - } - return FALSE; -} - -gboolean -nmc_arg_is_option (const char *str, const char *opt_name) -{ - const char *p; - - if (!str || !*str) - return FALSE; - - if (str[0] != '-') - return FALSE; - - p = (str[1] == '-') ? str + 2 : str + 1; - - return (*p ? (matches (p, opt_name) == 0) : FALSE); -} - - -/* - * Helper function to parse command-line arguments. - * arg_arr: description of arguments to look for - * last: whether these are last expected arguments - * argc: command-line argument array - * argv: command-line argument array size - * error: error set on a failure (when FALSE is returned) - * Returns: TRUE on success, FALSE on an error and sets 'error' - */ -gboolean -nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error) -{ - nmc_arg_t *p; - gboolean found; - gboolean have_mandatory; - - g_return_val_if_fail (arg_arr != NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - while (*argc > 0) { - found = FALSE; - - for (p = arg_arr; p->name; p++) { - if (strcmp (**argv, p->name) == 0) { - - if (p->found) { - /* Don't allow repeated arguments, because the argument of the same - * name could be used later on the line for another purpose. Assume - * that's the case and return. - */ - return TRUE; - } - - if (p->has_value) { - if (next_arg (argc, argv) != 0) { - g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("Error: value for '%s' argument is required."), *(*argv-1)); - return FALSE; - } - *(p->value) = **argv; - } - p->found = TRUE; - found = TRUE; - break; - } - } - - if (!found) { - have_mandatory = TRUE; - for (p = arg_arr; p->name; p++) { - if (p->mandatory && !p->found) { - have_mandatory = FALSE; - break; - } - } - - if (have_mandatory && !last) - return TRUE; - - if (p->name) - g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("Error: Argument '%s' was expected, but '%s' provided."), p->name, **argv); - else - g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("Error: Unexpected argument '%s'"), **argv); - return FALSE; - } - - next_arg (argc, argv); - } - - return TRUE; -} - -/* - * Convert SSID to a hex string representation. - * Caller has to free the returned string using g_free() - */ -char * -ssid_to_hex (const char *str, gsize len) -{ - GString *printable; - char *printable_str; - int i; - - if (str == NULL || len == 0) - return NULL; - - printable = g_string_new (NULL); - for (i = 0; i < len; i++) { - g_string_append_printf (printable, "%02X", (unsigned char) str[i]); - } - printable_str = g_string_free (printable, FALSE); - return printable_str; -} - -/* - * Converts IPv4 address from guint32 in network-byte order to text representation. - * Returns: text form of the IP or NULL (then error is set) - */ -char * -nmc_ip4_address_as_string (guint32 ip, GError **error) -{ - guint32 tmp_addr; - char buf[INET_ADDRSTRLEN]; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - memset (&buf, '\0', sizeof (buf)); - tmp_addr = ip; - - if (inet_ntop (AF_INET, &tmp_addr, buf, INET_ADDRSTRLEN)) { - return g_strdup (buf); - } else { - g_set_error (error, NMCLI_ERROR, 0, _("Error converting IP4 address '0x%X' to text form"), - ntohl (tmp_addr)); - return NULL; - } -} - -/* - * Converts IPv6 address in in6_addr structure to text representation. - * Returns: text form of the IP or NULL (then error is set) - */ -char * -nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error) -{ - char buf[INET6_ADDRSTRLEN]; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - memset (&buf, '\0', sizeof (buf)); - - if (inet_ntop (AF_INET6, ip, buf, INET6_ADDRSTRLEN)) { - return g_strdup (buf); - } else { - if (error) { - int j; - GString *ip6_str = g_string_new (NULL); - g_string_append_printf (ip6_str, "%02X", ip->s6_addr[0]); - for (j = 1; j < 16; j++) - g_string_append_printf (ip6_str, " %02X", ip->s6_addr[j]); - g_set_error (error, NMCLI_ERROR, 0, _("Error converting IP6 address '%s' to text form"), - ip6_str->str); - g_string_free (ip6_str, TRUE); - } - return NULL; - } -} - -/* - * Erase terminal line using ANSI escape sequences. - * It prints <ESC>[2K sequence to erase the line and then \r to return back - * to the beginning of the line. - * - * http://www.termsys.demon.co.uk/vtansi.htm - */ -void -nmc_terminal_erase_line (void) -{ - printf ("\33[2K\r"); - fflush (stdout); -} - -/* - * Print animated progress for an operation. - * Repeated calls of the function will show rotating slash in terminal followed - * by the string passed in 'str' argument. - */ -void -nmc_terminal_show_progress (const char *str) -{ - static int idx = 0; - const char slashes[4] = {'|', '/', '-', '\\'}; - - nmc_terminal_erase_line (); - printf ("%c %s", slashes[idx++], str ? str : ""); - fflush (stdout); - if (idx == 4) - idx = 0; -} - -const char * -nmc_term_color_sequence (NmcTermColor color) -{ - switch (color) { - case NMC_TERM_COLOR_BLACK: - return "\33[30m"; - break; - case NMC_TERM_COLOR_RED: - return "\33[31m"; - break; - case NMC_TERM_COLOR_GREEN: - return "\33[32m"; - break; - case NMC_TERM_COLOR_YELLOW: - return "\33[33m"; - break; - case NMC_TERM_COLOR_BLUE: - return "\33[34m"; - break; - case NMC_TERM_COLOR_MAGENTA: - return "\33[35m"; - break; - case NMC_TERM_COLOR_CYAN: - return "\33[36m"; - break; - case NMC_TERM_COLOR_WHITE: - return "\33[37m"; - break; - default: - return ""; - break; - } -} - -char * -nmc_colorize (NmcTermColor color, const char *fmt, ...) -{ - va_list args; - char *str, *colored; - const char *ansi_color, *color_end; - - va_start (args, fmt); - str = g_strdup_vprintf (fmt, args); - va_end (args); - - ansi_color = nmc_term_color_sequence (color); - if (*ansi_color) - color_end = "\33[0m"; - else - color_end = ""; - - colored = g_strdup_printf ("%s%s%s", ansi_color, str, color_end); - g_free (str); - return colored; -} - -/* - * Convert string to signed integer. - * If required, the resulting number is checked to be in the <min,max> range. - */ -gboolean -nmc_string_to_int_base (const char *str, - int base, - gboolean range_check, - long int min, - long int max, - long int *value) -{ - char *end; - long int tmp; - - errno = 0; - tmp = strtol (str, &end, base); - if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) { - return FALSE; - } - *value = tmp; - return TRUE; -} - -/* - * Convert string to unsigned integer. - * If required, the resulting number is checked to be in the <min,max> range. - */ -gboolean -nmc_string_to_uint_base (const char *str, - int base, - gboolean range_check, - unsigned long int min, - unsigned long int max, - unsigned long int *value) -{ - char *end; - unsigned long int tmp; - - errno = 0; - tmp = strtoul (str, &end, base); - if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) { - return FALSE; - } - *value = tmp; - return TRUE; -} - -gboolean -nmc_string_to_int (const char *str, - gboolean range_check, - long int min, - long int max, - long int *value) -{ - return nmc_string_to_int_base (str, 10, range_check, min, max, value); -} - -gboolean -nmc_string_to_uint (const char *str, - gboolean range_check, - unsigned long int min, - unsigned long int max, - unsigned long int *value) -{ - return nmc_string_to_uint_base (str, 10, range_check, min, max, value); -} - -gboolean -nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error) -{ - const char *s_true[] = { "true", "yes", "on", NULL }; - const char *s_false[] = { "false", "no", "off", NULL }; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - if (g_strcmp0 (str, "o") == 0) { - g_set_error (error, 1, 0, - _("'%s' is ambiguous (on x off)"), str); - return FALSE; - } - - if (nmc_string_is_valid (str, s_true, NULL)) - *val_bool = TRUE; - else if (nmc_string_is_valid (str, s_false, NULL)) - *val_bool = FALSE; - else { - g_set_error (error, 1, 0, - _("'%s' is not valid; use [%s] or [%s]"), - str, "true, yes, on", "false, no, off"); - return FALSE; - } - return TRUE; -} - -/* - * Ask user for input and return the string. - * The caller is responsible for freeing the returned string. - */ -char * -nmc_get_user_input (const char *ask_str) -{ - char *line = NULL; - size_t line_ln = 0; - ssize_t num; - - fprintf (stdout, "%s", ask_str); - num = getline (&line, &line_ln, stdin); - - /* Remove newline from the string */ - if (num < 1 || (num == 1 && line[0] == '\n')) { - g_free (line); - line = NULL; - } else { - if (line[num-1] == '\n') - line[num-1] = '\0'; - } - - return line; -} - -/* - * Split string in 'line' according to 'delim' to (argument) array. - */ -int -nmc_string_to_arg_array (const char *line, const char *delim, char ***argv, int *argc) -{ - int i = 0; - char **arr; - - arr = g_strsplit_set (line ? line : "", delim ? delim : " \t", 0); - while (arr && arr[i]) - i++; - - *argc = i; - *argv = arr; - - return 0; -} - -/* - * Check whether 'input' is contained in 'allowed' array. It performs case - * insensitive comparison and supports shortcut strings if they are unique. - * Returns: a pointer to found string in allowed array on success or NULL. - * On failure: error->code : 0 - string not found; 1 - string is ambiguous - */ -const char * -nmc_string_is_valid (const char *input, const char **allowed, GError **error) -{ - const char **p; - size_t input_ln, p_len; - gboolean prev_match = FALSE; - const char *ret = NULL; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - if (!input || !*input) - goto finish; - - input_ln = strlen (input); - for (p = allowed; p && *p; p++) { - p_len = strlen (*p); - if (g_ascii_strncasecmp (input, *p, input_ln) == 0) { - if (input_ln == p_len) { - ret = *p; - break; - } - if (!prev_match) - ret = *p; - else { - g_set_error (error, 1, 1, _("'%s' is ambiguous (%s x %s)"), - input, ret, *p); - return NULL; - } - prev_match = TRUE; - } - } - -finish: - if (ret == NULL) { - char *valid_vals = g_strjoinv (", ", (char **) allowed); - if (!input || !*input) { - g_set_error (error, 1, 0, _("missing name, try one of [%s]"), - valid_vals); - } else { - g_set_error (error, 1, 0, _("'%s' not among [%s]"), - input ? input : "", valid_vals); - } - - g_free (valid_vals); - } - return ret; -} - -/* - * Convert string array (char **) to GSList. - * - * Returns: pointer to newly created GSList. Caller should free it. - */ -GSList * -nmc_util_strv_to_slist (char **strv) -{ - GSList *list = NULL; - guint i = 0; - - while (strv && strv[i]) - list = g_slist_prepend (list, g_strdup (strv[i++])); - - return g_slist_reverse (list); -} - -/* - * Wrapper function for g_strsplit_set() that removes empty strings - * from the vector as they are not useful in most cases. - */ -char ** -nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens) -{ - char **result; - uint i; - uint j; - - result = g_strsplit_set (str, delimiter, max_tokens); - - /* remove empty strings */ - for (i = 0; result && result[i]; i++) { - if (*(result[i]) == '\0') { - g_free (result[i]); - for (j = i; result[j]; j++) - result[j] = result[j + 1]; - i--; - } - } - return result; -} - -/* - * Find out how many columns an UTF-8 string occupies on the screen - */ -int -nmc_string_screen_width (const char *start, const char *end) -{ - int width = 0; - - if (end == NULL) - end = start + strlen (start); - - while (start < end) { - width += g_unichar_iswide (g_utf8_get_char (start)) ? 2 : g_unichar_iszerowidth (g_utf8_get_char (start)) ? 0 : 1; - start = g_utf8_next_char (start); - } - return width; -} - -void -set_val_str (NmcOutputField fields_array[], guint32 idx, char *value) -{ - fields_array[idx].value = value; - fields_array[idx].value_is_array = FALSE; - fields_array[idx].free_value = TRUE; -} - -void -set_val_strc (NmcOutputField fields_array[], guint32 idx, const char *value) -{ - fields_array[idx].value = (char *) value; - fields_array[idx].value_is_array = FALSE; - fields_array[idx].free_value = FALSE; -} - -void -set_val_arr (NmcOutputField fields_array[], guint32 idx, char **value) -{ - fields_array[idx].value = value; - fields_array[idx].value_is_array = TRUE; - fields_array[idx].free_value = TRUE; -} - -void -set_val_arrc (NmcOutputField fields_array[], guint32 idx, const char **value) -{ - fields_array[idx].value = (char **) value; - fields_array[idx].value_is_array = TRUE; - fields_array[idx].free_value = FALSE; -} - -/* - * Free 'value' members in array of NmcOutputField - */ -void -nmc_free_output_field_values (NmcOutputField fields_array[]) -{ - NmcOutputField *iter = fields_array; - - while (iter && iter->name) { - if (iter->free_value) { - if (iter->value_is_array) - g_strfreev ((char **) iter->value); - else - g_free ((char *) iter->value); - iter->value = NULL; - } - iter++; - } -} - -/** - * parse_output_fields: - * @field_str: comma-separated field names to parse - * @fields_array: array of allowed fields - * @parse_groups: whether the fields can contain group prefix (e.g. general.driver) - * @group_fields: (out) (allow-none): array of field names for particular groups - * @error: (out) (allow-none): location to store error, or %NULL - * - * Parses comma separated fields in @fields_str according to @fields_array. - * When @parse_groups is %TRUE, fields can be in the form 'group.field'. Then - * @group_fields will be filled with the required field for particular group. - * @group_fields array corresponds to the returned array. - * Examples: - * @field_str: "type,name,uuid" | "ip4,general.device" | "ip4.address,ip6" - * returned array: 2 0 1 | 7 0 | 7 9 - * @group_fields: NULL NULL NULL | NULL "device" | "address" NULL - * - * Returns: #GArray with indices representing fields in @fields_array. - * Caller is responsible for freeing the array. - */ -GArray * -parse_output_fields (const char *fields_str, - const NmcOutputField fields_array[], - gboolean parse_groups, - GPtrArray **group_fields, - GError **error) -{ - char **fields, **iter; - GArray *array; - int i, j; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - g_return_val_if_fail (group_fields == NULL || *group_fields == NULL, NULL); - - array = g_array_new (FALSE, FALSE, sizeof (int)); - if (parse_groups && group_fields) - *group_fields = g_ptr_array_new_full (20, (GDestroyNotify) g_free); - - /* Split supplied fields string */ - fields = g_strsplit_set (fields_str, ",", -1); - for (iter = fields; iter && *iter; iter++) { - int idx = -1; - - g_strstrip (*iter); - if (parse_groups) { - /* e.g. "general.device,general.driver,ip4,ip6" */ - gboolean found = FALSE; - char *left = *iter; - char *right = strchr (*iter, '.'); - - if (right) - *right++ = '\0'; - - for (i = 0; fields_array[i].name; i++) { - if (strcasecmp (left, fields_array[i].name) == 0) { - NmcOutputField *valid_names = fields_array[i].group; - idx = i; - if (!right && !valid_names) { - found = TRUE; - break; - } - for (j = 0; valid_names && valid_names[j].name; j++) { - if (!right || strcasecmp (right, valid_names[j].name) == 0) { - found = TRUE; - break; - } - } - } - if (found) - break; - } - if (found) { - /* Add index to array, and field name (or NULL) to group_fields array */ - g_array_append_val (array, idx); - if (group_fields && *group_fields) - g_ptr_array_add (*group_fields, g_strdup (right)); - } - if (right) - *(right-1) = '.'; /* Restore the original string */ - } else { - /* e.g. "general,ip4,ip6" */ - for (i = 0; fields_array[i].name; i++) { - if (strcasecmp (*iter, fields_array[i].name) == 0) { - g_array_append_val (array, i); - break; - } - } - } - - /* Field was not found - error case */ - if (fields_array[i].name == NULL) { - /* Set GError */ - if (!strcasecmp (*iter, "all") || !strcasecmp (*iter, "common")) - g_set_error (error, NMCLI_ERROR, 0, _("field '%s' has to be alone"), *iter); - else { - char *allowed_fields = nmc_get_allowed_fields (fields_array, idx); - g_set_error (error, NMCLI_ERROR, 1, _("invalid field '%s'; allowed fields: %s"), - *iter, allowed_fields); - g_free (allowed_fields); - } - - /* Free arrays on error */ - g_array_free (array, TRUE); - array = NULL; - if (group_fields && *group_fields) { - g_ptr_array_free (*group_fields, TRUE); - *group_fields = NULL; - } - goto done; - } - } -done: - if (fields) - g_strfreev (fields); - return array; -} - -/** -* nmc_get_allowed_fields: -* @fields_array: array of fields -* @group_idx: index to the array (for second-level array in 'group' member), -* or -1 -* -* Returns: string of allowed fields names. -* Caller is responsible for freeing the array. -*/ -char * -nmc_get_allowed_fields (const NmcOutputField fields_array[], int group_idx) -{ - GString *allowed_fields = g_string_sized_new (256); - int i; - - if (group_idx != -1 && fields_array[group_idx].group) { - NmcOutputField *second_level = fields_array[group_idx].group; - for (i = 0; second_level[i].name; i++) - g_string_append_printf (allowed_fields, "%s.%s,", - fields_array[group_idx].name, second_level[i].name); - } else { - for (i = 0; fields_array[i].name; i++) - g_string_append_printf (allowed_fields, "%s,", fields_array[i].name); - } - g_string_truncate (allowed_fields, allowed_fields->len - 1); - - return g_string_free (allowed_fields, FALSE); -} - -gboolean -nmc_terse_option_check (NMCPrintOutput print_output, const char *fields, GError **error) -{ - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - if (print_output == NMC_PRINT_TERSE) { - if (!fields) { - g_set_error_literal (error, NMCLI_ERROR, 0, _("Option '--terse' requires specifying '--fields'")); - return FALSE; - } else if ( !strcasecmp (fields, "all") - || !strcasecmp (fields, "common")) { - g_set_error (error, NMCLI_ERROR, 0, _("Option '--terse' requires specific '--fields' option values , not '%s'"), fields); - return FALSE; - } - } - return TRUE; -} - -NmcOutputField * -nmc_dup_fields_array (NmcOutputField fields[], size_t size, guint32 flags) -{ - NmcOutputField *row; - - row = g_malloc0 (size); - memcpy (row, fields, size); - row[0].flags = flags; - - return row; -} - -void -nmc_empty_output_fields (NmCli *nmc) -{ - guint i; - - /* Free values in field structure */ - for (i = 0; i < nmc->output_data->len; i++) { - NmcOutputField *fld_arr = g_ptr_array_index (nmc->output_data, i); - nmc_free_output_field_values (fld_arr); - } - - /* Empty output_data array */ - if (nmc->output_data->len > 0) - g_ptr_array_remove_range (nmc->output_data, 0, nmc->output_data->len); - - if (nmc->print_fields.indices) { - g_array_free (nmc->print_fields.indices, TRUE); - nmc->print_fields.indices = NULL; - } -} - -static char * -get_value_to_print (NmcOutputField *fields, - gboolean field_name, - const char *not_set_str, - gboolean *dealloc) -{ - gboolean is_array = fields->value_is_array; - char *value; - - if (field_name) - value = _(fields->name_l10n); - else - value = fields->value ? - (is_array ? g_strjoinv (" | ", (char **) fields->value) : - (char *) fields->value) : - (char *) not_set_str; - *dealloc = fields->value && is_array && !field_name; - return value; -} - -/* - * Print both headers or values of 'field_values' array. - * Entries to print and their order are specified via indices in - * 'nmc->print_fields.indices' array. - * Various flags influencing the output of fields are set up in the first item - * of 'field_values' array. - */ -void -print_required_fields (NmCli *nmc, const NmcOutputField field_values[]) -{ - GString *str; - int width1, width2; - int table_width = 0; - char *line = NULL; - char *indent_str; - const char *not_set_str = "--"; - int i; - const NmcPrintFields fields = nmc->print_fields; - gboolean multiline = nmc->multiline_output; - gboolean terse = (nmc->print_output == NMC_PRINT_TERSE); - gboolean pretty = (nmc->print_output == NMC_PRINT_PRETTY); - gboolean escape = nmc->escape_values; - gboolean main_header_add = field_values[0].flags & NMC_OF_FLAG_MAIN_HEADER_ADD; - gboolean main_header_only = field_values[0].flags & NMC_OF_FLAG_MAIN_HEADER_ONLY; - gboolean field_names = field_values[0].flags & NMC_OF_FLAG_FIELD_NAMES; - gboolean section_prefix = field_values[0].flags & NMC_OF_FLAG_SECTION_PREFIX; - gboolean main_header = main_header_add || main_header_only; - - /* No headers are printed in terse mode: - * - neither main header nor field (column) names - */ - if ((main_header_only || field_names) && terse) - return; - - if (multiline) { - /* --- Multiline mode --- */ - enum { ML_HEADER_WIDTH = 79 }; - enum { ML_VALUE_INDENT = 40 }; - if (main_header && pretty) { - /* Print the main header */ - int header_width = nmc_string_screen_width (fields.header_name, NULL) + 4; - table_width = header_width < ML_HEADER_WIDTH ? ML_HEADER_WIDTH : header_width; - - line = g_strnfill (ML_HEADER_WIDTH, '='); - width1 = strlen (fields.header_name); - width2 = nmc_string_screen_width (fields.header_name, NULL); - printf ("%s\n", line); - printf ("%*s\n", (table_width + width2)/2 + width1 - width2, fields.header_name); - printf ("%s\n", line); - g_free (line); - } - - /* Print values */ - if (!main_header_only && !field_names) { - for (i = 0; i < fields.indices->len; i++) { - char *tmp; - int idx = g_array_index (fields.indices, int, i); - gboolean is_array = field_values[idx].value_is_array; - - /* section prefix can't be an array */ - g_assert (!is_array || !section_prefix || idx != 0); - - if (section_prefix && idx == 0) /* The first field is section prefix */ - continue; - - if (is_array) { - /* value is a null-terminated string array */ - const char **p; - int j; - - for (p = (const char **) field_values[idx].value, j = 1; p && *p; p++, j++) { - tmp = g_strdup_printf ("%s%s%s[%d]:", - section_prefix ? (const char*) field_values[0].value : "", - section_prefix ? "." : "", - _(field_values[idx].name_l10n), - j); - width1 = strlen (tmp); - width2 = nmc_string_screen_width (tmp, NULL); - printf ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, - *p ? *p : not_set_str); - g_free (tmp); - } - } else { - /* value is a string */ - const char *hdr_name = (const char*) field_values[0].value; - const char *val = (const char*) field_values[idx].value; - - tmp = g_strdup_printf ("%s%s%s:", - section_prefix ? hdr_name : "", - section_prefix ? "." : "", - _(field_values[idx].name_l10n)); - width1 = strlen (tmp); - width2 = nmc_string_screen_width (tmp, NULL); - printf ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, - val ? val : not_set_str); - g_free (tmp); - } - } - if (pretty) { - line = g_strnfill (ML_HEADER_WIDTH, '-'); - printf ("%s\n", line); - g_free (line); - } - } - return; - } - - /* --- Tabular mode: each line = one object --- */ - str = g_string_new (NULL); - - for (i = 0; i < fields.indices->len; i++) { - int idx = g_array_index (fields.indices, int, i); - gboolean dealloc; - char *value = get_value_to_print ((NmcOutputField *) field_values+idx, field_names, not_set_str, &dealloc); - - if (terse) { - if (escape) { - const char *p = value; - while (*p) { - if (*p == ':' || *p == '\\') - g_string_append_c (str, '\\'); /* Escaping by '\' */ - g_string_append_c (str, *p); - p++; - } - } - else - g_string_append_printf (str, "%s", value); - g_string_append_c (str, ':'); /* Column separator */ - } else { - width1 = strlen (value); - width2 = nmc_string_screen_width (value, NULL); /* Width of the string (in screen colums) */ - g_string_append_printf (str, "%-*s", field_values[idx].width + width1 - width2, strlen (value) > 0 ? value : "--"); - g_string_append_c (str, ' '); /* Column separator */ - table_width += field_values[idx].width + width1 - width2 + 1; - } - - if (dealloc) - g_free (value); - } - - /* Print the main table header */ - if (main_header && pretty) { - int header_width = nmc_string_screen_width (fields.header_name, NULL) + 4; - table_width = table_width < header_width ? header_width : table_width; - - line = g_strnfill (table_width, '='); - width1 = strlen (fields.header_name); - width2 = nmc_string_screen_width (fields.header_name, NULL); - printf ("%s\n", line); - printf ("%*s\n", (table_width + width2)/2 + width1 - width2, fields.header_name); - printf ("%s\n", line); - g_free (line); - } - - /* Print actual values */ - if (!main_header_only && str->len > 0) { - g_string_truncate (str, str->len-1); /* Chop off last column separator */ - if (fields.indent > 0) { - indent_str = g_strnfill (fields.indent, ' '); - g_string_prepend (str, indent_str); - g_free (indent_str); - } - printf ("%s\n", str->str); - } - - /* Print horizontal separator */ - if (!main_header_only && field_names && pretty) { - if (str->len > 0) { - line = g_strnfill (table_width, '-'); - printf ("%s\n", line); - g_free (line); - } - } - - g_string_free (str, TRUE); -} - -/* - * Print nmc->output_data - * - * It first finds out maximal string length in columns and fill the value to - * 'width' member of NmcOutputField, so that columns in tabular output are - * properly aligned. Then each object (row in tabular) is printed using - * print_required_fields() function. - */ -void -print_data (NmCli *nmc) -{ - int i, j; - size_t len; - NmcOutputField *row; - int num_fields = 0; - - if (!nmc->output_data || nmc->output_data->len < 1) - return; - - /* How many fields? */ - row = g_ptr_array_index (nmc->output_data, 0); - while (row->name) { - num_fields++; - row++; - } - - /* Find out maximal string lengths */ - for (i = 0; i < num_fields; i++) { - size_t max_width = 0; - for (j = 0; j < nmc->output_data->len; j++) { - gboolean field_names, dealloc; - char *value; - row = g_ptr_array_index (nmc->output_data, j); - field_names = row[0].flags & NMC_OF_FLAG_FIELD_NAMES; - value = get_value_to_print (row+i, field_names, "--", &dealloc); - len = nmc_string_screen_width (value, NULL); - max_width = len > max_width ? len : max_width; - if (dealloc) - g_free (value); - } - for (j = 0; j < nmc->output_data->len; j++) { - row = g_ptr_array_index (nmc->output_data, j); - row[i].width = max_width + 1; - } - } - - /* Now we can print the data. */ - for (i = 0; i < nmc->output_data->len; i++) { - row = g_ptr_array_index (nmc->output_data, i); - print_required_fields (nmc, row); - } -} - -/* -* Compare versions of nmcli and NM daemon. -* Return: TRUE - the versions match (when only major and minor match, print a warning) -* FALSE - versions mismatch -*/ -gboolean -nmc_versions_match (NmCli *nmc) -{ - const char *nm_ver = NULL; - const char *dot; - gboolean match = FALSE; - - g_return_val_if_fail (nmc != NULL, FALSE); - - /* --nocheck option - don't compare the versions */ - if (nmc->nocheck_ver) - return TRUE; - - nmc->get_client (nmc); - nm_ver = nm_client_get_version (nmc->client); - if (nm_ver) { - if (!strcmp (nm_ver, VERSION)) - match = TRUE; - else { - dot = strchr (nm_ver, '.'); - if (dot) { - dot = strchr (dot + 1, '.'); - if (dot && !strncmp (nm_ver, VERSION, dot-nm_ver)) { - fprintf(stderr, - _("Warning: nmcli (%s) and NetworkManager (%s) versions don't match. Use --nocheck to suppress the warning.\n"), - VERSION, nm_ver); - match = TRUE; - } - } - } - } - - if (!match) { - g_string_printf (nmc->return_text, _("Error: nmcli (%s) and NetworkManager (%s) versions don't match. Force execution using --nocheck, but the results are unpredictable."), - VERSION, nm_ver ? nm_ver : _("unknown")); - nmc->return_value = NMC_RESULT_ERROR_VERSIONS_MISMATCH; - } - - return match; -} - |