2010-02-25 09:52:30 -08:00
/* 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 .
*
2012-01-03 15:07:17 +01:00
* ( C ) Copyright 2010 - 2012 Red Hat , Inc .
2010-02-25 09:52:30 -08:00
*/
2011-02-16 17:36:50 +01:00
/* Generated configuration file */
# include "config.h"
2010-02-25 09:52:30 -08:00
# include <stdio.h>
# include <string.h>
2013-01-16 12:28:37 +01:00
# include <stdlib.h>
# include <errno.h>
2010-02-25 09:52:30 -08:00
2012-01-05 16:30:22 +01:00
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
2010-02-25 09:52:30 -08:00
# include <glib.h>
2010-03-18 15:39:15 +01:00
# include <glib/gi18n.h>
2011-02-10 14:21:18 +01:00
# include <dbus/dbus-glib-bindings.h>
2010-02-25 09:52:30 -08:00
# include "utils.h"
int
matches ( const char * cmd , const char * pattern )
{
int len = strlen ( cmd ) ;
if ( len > strlen ( pattern ) )
return - 1 ;
return memcmp ( pattern , cmd , len ) ;
}
int
next_arg ( int * argc , char * * * argv )
{
2012-11-16 22:43:29 +01:00
int arg_num = * argc ;
if ( arg_num > 0 ) {
2010-02-25 09:52:30 -08:00
( * argc ) - - ;
( * argv ) + + ;
}
2012-11-16 22:43:29 +01:00
if ( arg_num < = 1 )
return - 1 ;
2010-02-25 09:52:30 -08:00
return 0 ;
}
2013-04-18 11:25:49 +02:00
gboolean
nmc_arg_is_help ( const char * arg )
{
2013-04-18 12:42:54 +02:00
if ( ! arg )
return FALSE ;
2013-04-18 11:25:49 +02:00
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 ;
}
2013-01-16 12:26:45 +01:00
/*
* 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 & & 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 ;
}
2010-03-24 23:28:00 +01:00
/*
* Convert SSID to a printable form .
* If it is an UTF - 8 string , enclose it in quotes and return it .
* Otherwise convert it to a hex string representation .
* Caller has to free the returned string using g_free ( )
*/
char *
ssid_to_printable ( const char * str , gsize len )
{
GString * printable ;
char * printable_str ;
int i ;
if ( str = = NULL | | len = = 0 )
2012-04-28 22:54:02 +02:00
return NULL ;
2010-03-24 23:28:00 +01:00
if ( g_utf8_validate ( str , len , NULL ) )
return g_strdup_printf ( " '%.*s' " , ( int ) len , str ) ;
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 ;
}
2012-01-05 16:30:22 +01:00
/*
* 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 )
{
struct in_addr tmp_addr ;
char buf [ INET_ADDRSTRLEN ] ;
g_return_val_if_fail ( error = = NULL | | * error = = NULL , NULL ) ;
memset ( & buf , ' \0 ' , sizeof ( buf ) ) ;
tmp_addr . s_addr = ip ;
if ( inet_ntop ( AF_INET , & tmp_addr , buf , INET_ADDRSTRLEN ) ) {
return g_strdup ( buf ) ;
} else {
2012-07-25 13:57:45 +02:00
g_set_error ( error , NMCLI_ERROR , 0 , _ ( " Error converting IP4 address '0x%X' to text form " ) ,
2012-01-05 16:30:22 +01:00
ntohl ( tmp_addr . s_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 ] ) ;
2012-07-25 13:57:45 +02:00
g_set_error ( error , NMCLI_ERROR , 0 , _ ( " Error converting IP6 address '%s' to text form " ) ,
2012-01-05 16:30:22 +01:00
ip6_str - > str ) ;
g_string_free ( ip6_str , TRUE ) ;
}
return NULL ;
}
}
2012-04-28 22:32:21 +01:00
/*
* Erase terminal line using ANSI escape sequences .
* It prints < ESC > [ 2 K 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 ;
}
2013-01-16 12:28:37 +01:00
/*
* 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 ) ;
}
2012-11-21 16:53:23 +01:00
/*
* 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 ;
2013-04-15 13:40:14 +02:00
ssize_t num ;
2012-11-21 16:53:23 +01:00
fprintf ( stdout , " %s " , ask_str ) ;
2013-04-15 13:40:14 +02:00
num = getline ( & line , & line_ln , stdin ) ;
2012-11-21 16:53:23 +01:00
/* Remove newline from the string */
2013-04-15 13:40:14 +02:00
if ( num < 1 | | ( num = = 1 & & line [ 0 ] = = ' \n ' ) ) {
2012-11-21 16:53:23 +01:00
g_free ( line ) ;
line = NULL ;
} else {
2013-04-15 13:40:14 +02:00
if ( line [ num - 1 ] = = ' \n ' )
line [ num - 1 ] = ' \0 ' ;
2012-11-21 16:53:23 +01:00
}
return line ;
}
2012-11-22 11:56:06 +01:00
/*
* 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 ;
}
2013-04-08 09:25:44 +02:00
/*
* 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 ) ;
g_set_error ( error , 1 , 0 , _ ( " '%s' not among [%s] " ) ,
input ? input : " " , valid_vals ) ;
g_free ( valid_vals ) ;
}
return ret ;
}
2010-04-26 17:32:18 +02:00
/*
* 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 ;
}
2012-01-03 15:07:17 +01:00
void
2013-03-05 15:50:11 +01:00
set_val_str ( NmcOutputField fields_array [ ] , guint32 idx , char * value )
2012-01-03 15:07:17 +01:00
{
fields_array [ idx ] . flags = 0 ;
fields_array [ idx ] . value = value ;
}
void
2013-03-05 15:50:11 +01:00
set_val_arr ( NmcOutputField fields_array [ ] , guint32 idx , char * * value )
2012-01-03 15:07:17 +01:00
{
fields_array [ idx ] . flags = NMC_OF_FLAG_ARRAY ;
fields_array [ idx ] . value = value ;
}
2013-03-25 10:44:15 -04:00
/*
* Free ' value ' members in array of NmcOutputField
*/
void
nmc_free_output_field_values ( NmcOutputField fields_array [ ] )
{
int idx = 0 ;
while ( fields_array & & fields_array [ idx ] . value ) {
if ( fields_array [ idx ] . flags & NMC_OF_FLAG_ARRAY )
g_strfreev ( fields_array [ idx ] . value ) ;
else
g_free ( fields_array [ idx ] . value ) ;
idx + + ;
}
}
2010-03-18 15:39:15 +01:00
/*
* Parse comma separated fields in ' fields_str ' according to ' fields_array ' .
* IN : ' field_str ' : comma - separated fields names
* ' fields_array ' : array of allowed fields
* RETURN : GArray with indices representing fields in ' fields_array ' .
2010-03-20 14:08:06 +01:00
* Caller is responsible to free it .
2010-03-18 15:39:15 +01:00
*/
GArray *
parse_output_fields ( const char * fields_str , const NmcOutputField fields_array [ ] , GError * * error )
{
char * * fields , * * iter ;
GArray * array ;
int i ;
g_return_val_if_fail ( error = = NULL | | * error = = NULL , NULL ) ;
array = g_array_new ( FALSE , FALSE , sizeof ( int ) ) ;
/* Split supplied fields string */
fields = g_strsplit_set ( fields_str , " , " , - 1 ) ;
for ( iter = fields ; iter & & * iter ; iter + + ) {
for ( i = 0 ; fields_array [ i ] . name ; i + + ) {
if ( strcasecmp ( * iter , fields_array [ i ] . name ) = = 0 ) {
g_array_append_val ( array , i ) ;
break ;
}
}
if ( fields_array [ i ] . name = = NULL ) {
if ( ! strcasecmp ( * iter , " all " ) | | ! strcasecmp ( * iter , " common " ) )
2012-07-25 13:57:45 +02:00
g_set_error ( error , NMCLI_ERROR , 0 , _ ( " field '%s' has to be alone " ) , * iter ) ;
2010-03-18 15:39:15 +01:00
else
2012-07-25 13:57:45 +02:00
g_set_error ( error , NMCLI_ERROR , 1 , _ ( " invalid field '%s' " ) , * iter ) ;
2010-03-18 15:39:15 +01:00
g_array_free ( array , TRUE ) ;
array = NULL ;
goto done ;
}
}
done :
2010-03-19 15:46:25 +01:00
if ( fields )
g_strfreev ( fields ) ;
2010-03-18 15:39:15 +01:00
return array ;
}
2010-03-22 18:43:28 +01:00
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 ) {
2012-07-25 13:57:45 +02:00
g_set_error_literal ( error , NMCLI_ERROR , 0 , _ ( " Option '--terse' requires specifying '--fields' " ) ) ;
2010-03-22 18:43:28 +01:00
return FALSE ;
} else if ( ! strcasecmp ( fields , " all " )
| | ! strcasecmp ( fields , " common " ) ) {
2012-07-25 13:57:45 +02:00
g_set_error ( error , NMCLI_ERROR , 0 , _ ( " Option '--terse' requires specific '--fields' option values , not '%s' " ) , fields ) ;
2010-03-22 18:43:28 +01:00
return FALSE ;
}
}
return TRUE ;
}
2010-03-20 14:08:06 +01:00
/*
* Print both headers or values of ' field_values ' array .
* Entries to print and their order are specified via indices
* in ' fields . indices ' array .
* ' fields . flags ' specify various aspects influencing the output .
*/
2010-03-18 15:39:15 +01:00
void
print_fields ( const NmcPrintFields fields , const NmcOutputField field_values [ ] )
{
GString * str ;
int width1 , width2 ;
int table_width = 0 ;
char * line = NULL ;
char * indent_str ;
2012-06-04 12:25:43 +02:00
const char * not_set_str = " -- " ;
2012-01-03 15:07:17 +01:00
int i ;
2010-03-18 15:39:15 +01:00
gboolean multiline = fields . flags & NMC_PF_FLAG_MULTILINE ;
gboolean terse = fields . flags & NMC_PF_FLAG_TERSE ;
gboolean pretty = fields . flags & NMC_PF_FLAG_PRETTY ;
2010-03-24 19:05:35 +01:00
gboolean main_header_add = fields . flags & NMC_PF_FLAG_MAIN_HEADER_ADD ;
gboolean main_header_only = fields . flags & NMC_PF_FLAG_MAIN_HEADER_ONLY ;
2010-03-22 18:43:28 +01:00
gboolean field_names = fields . flags & NMC_PF_FLAG_FIELD_NAMES ;
2010-03-18 15:39:15 +01:00
gboolean escape = fields . flags & NMC_PF_FLAG_ESCAPE ;
2010-03-24 19:05:35 +01:00
gboolean section_prefix = fields . flags & NMC_PF_FLAG_SECTION_PREFIX ;
gboolean main_header = main_header_add | | main_header_only ;
2010-03-18 15:39:15 +01:00
2010-03-20 14:08:06 +01:00
/* No headers are printed in terse mode:
2010-03-22 18:43:28 +01:00
* - neither main header nor field ( column ) names
2010-03-20 14:08:06 +01:00
*/
2010-03-24 19:05:35 +01:00
if ( ( main_header_only | | field_names ) & & terse )
2010-03-18 15:39:15 +01:00
return ;
if ( multiline ) {
/* --- Multiline mode --- */
2010-03-20 14:08:06 +01:00
enum { ML_HEADER_WIDTH = 79 } ;
2011-09-07 12:20:56 +02:00
enum { ML_VALUE_INDENT = 40 } ;
2010-03-22 18:43:28 +01:00
if ( main_header & & pretty ) {
/* Print the main header */
2010-04-26 17:32:18 +02:00
int header_width = nmc_string_screen_width ( fields . header_name , NULL ) + 4 ;
2010-03-20 14:08:06 +01:00
table_width = header_width < ML_HEADER_WIDTH ? ML_HEADER_WIDTH : header_width ;
line = g_strnfill ( ML_HEADER_WIDTH , ' = ' ) ;
2010-03-18 15:39:15 +01:00
width1 = strlen ( fields . header_name ) ;
2010-04-26 17:32:18 +02:00
width2 = nmc_string_screen_width ( fields . header_name , NULL ) ;
2010-03-18 15:39:15 +01:00
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 */
2010-03-24 19:05:35 +01:00
if ( ! main_header_only & & ! field_names ) {
2010-03-18 15:39:15 +01:00
for ( i = 0 ; i < fields . indices - > len ; i + + ) {
char * tmp ;
2012-01-03 15:07:17 +01:00
int idx = g_array_index ( fields . indices , int , i ) ;
guint32 value_is_array = field_values [ idx ] . flags & NMC_OF_FLAG_ARRAY ;
/* section prefix can't be an array */
g_assert ( ! value_is_array | | ! section_prefix | | idx ! = 0 ) ;
2010-03-24 19:05:35 +01:00
if ( section_prefix & & idx = = 0 ) /* The first field is section prefix */
continue ;
2012-01-03 15:07:17 +01:00
if ( value_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 ) ;
printf ( " %-*s%s \n " , terse ? 0 : ML_VALUE_INDENT , 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 ) ) ;
printf ( " %-*s%s \n " , terse ? 0 : ML_VALUE_INDENT , tmp , val ? val : not_set_str ) ;
g_free ( tmp ) ;
}
2010-03-18 15:39:15 +01:00
}
if ( pretty ) {
2010-03-20 14:08:06 +01:00
line = g_strnfill ( ML_HEADER_WIDTH , ' - ' ) ;
2010-03-18 15:39:15 +01:00
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 + + ) {
2012-01-03 15:07:17 +01:00
int idx = g_array_index ( fields . indices , int , i ) ;
guint32 value_is_array = field_values [ idx ] . flags & NMC_OF_FLAG_ARRAY ;
char * value ;
2010-03-22 18:43:28 +01:00
if ( field_names )
2010-03-18 15:39:15 +01:00
value = _ ( field_values [ idx ] . name_l10n ) ;
else
2012-01-03 15:07:17 +01:00
value = field_values [ idx ] . value ?
( value_is_array ? g_strjoinv ( " | " , ( char * * ) field_values [ idx ] . value ) : ( char * ) field_values [ idx ] . value ) :
( char * ) not_set_str ;
2010-03-18 15:39:15 +01:00
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 + + ;
}
}
2012-01-03 15:07:17 +01:00
else
2010-03-18 15:39:15 +01:00
g_string_append_printf ( str , " %s " , value ) ;
g_string_append_c ( str , ' : ' ) ; /* Column separator */
} else {
width1 = strlen ( value ) ;
2010-04-26 17:32:18 +02:00
width2 = nmc_string_screen_width ( value , NULL ) ; /* Width of the string (in screen colums) */
2012-01-03 15:07:17 +01:00
g_string_append_printf ( str , " %-*s " , field_values [ idx ] . width + width1 - width2 , strlen ( value ) > 0 ? value : " -- " ) ;
2010-03-18 15:39:15 +01:00
g_string_append_c ( str , ' ' ) ; /* Column separator */
table_width + = field_values [ idx ] . width + width1 - width2 + 1 ;
}
2012-01-03 15:07:17 +01:00
2012-01-06 14:47:34 +01:00
if ( value_is_array & & field_values [ idx ] . value & & ! field_values )
2012-01-03 15:07:17 +01:00
g_free ( value ) ;
2010-03-18 15:39:15 +01:00
}
2010-03-22 18:43:28 +01:00
/* Print the main table header */
if ( main_header & & pretty ) {
2010-04-26 17:32:18 +02:00
int header_width = nmc_string_screen_width ( fields . header_name , NULL ) + 4 ;
2010-03-20 14:08:06 +01:00
table_width = table_width < header_width ? header_width : table_width ;
2010-03-18 15:39:15 +01:00
line = g_strnfill ( table_width , ' = ' ) ;
width1 = strlen ( fields . header_name ) ;
2010-04-26 17:32:18 +02:00
width2 = nmc_string_screen_width ( fields . header_name , NULL ) ;
2010-03-18 15:39:15 +01:00
printf ( " %s \n " , line ) ;
printf ( " %*s \n " , ( table_width + width2 ) / 2 + width1 - width2 , fields . header_name ) ;
printf ( " %s \n " , line ) ;
g_free ( line ) ;
}
2010-03-20 14:08:06 +01:00
/* Print actual values */
2010-03-24 19:05:35 +01:00
if ( ! main_header_only & & str - > len > 0 ) {
2010-03-18 15:39:15 +01:00
g_string_truncate ( str , str - > len - 1 ) ; /* Chop off last column separator */
if ( fields . indent > 0 ) {
indent_str = g_strnfill ( fields . indent , ' ' ) ;
2010-03-20 14:08:06 +01:00
g_string_prepend ( str , indent_str ) ;
2010-03-18 15:39:15 +01:00
g_free ( indent_str ) ;
}
printf ( " %s \n " , str - > str ) ;
}
2010-03-20 14:08:06 +01:00
/* Print horizontal separator */
2010-03-24 19:05:35 +01:00
if ( ! main_header_only & & field_names & & pretty ) {
2010-03-18 15:39:15 +01:00
if ( str - > len > 0 ) {
line = g_strnfill ( table_width , ' - ' ) ;
printf ( " %s \n " , line ) ;
g_free ( line ) ;
}
}
g_string_free ( str , TRUE ) ;
}
2011-02-16 17:36:50 +01:00
/*
* 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 ;
}