2016-04-26 15:04:55 +02:00
/*
* Copyright ( C ) 2016 Red Hat , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
# include <dlfcn.h>
# include "internal.h"
# include "virjson.h"
# include "qemu/qemu_monitor.h"
# include "qemu/qemu_monitor_json.h"
2022-02-14 15:57:21 +01:00
# define LIBVIRT_QEMU_MONITOR_PRIV_H_ALLOW
# include "qemu/qemu_monitor_priv.h"
2017-11-03 13:09:47 +01:00
# define REAL_SYM(realFunc) \
do { \
if ( ! realFunc & & ! ( realFunc = dlsym ( RTLD_NEXT , __FUNCTION__ ) ) ) { \
fprintf ( stderr , " Cannot find real '%s' symbol \n " , \
__FUNCTION__ ) ; \
abort ( ) ; \
} \
2016-04-26 15:04:55 +02:00
} while ( 0 )
2018-05-03 17:29:36 +02:00
static bool first = true ;
2016-04-26 15:04:55 +02:00
2018-05-03 17:34:43 +02:00
static void
printLineSkipEmpty ( const char * line ,
FILE * fp )
{
const char * p ;
for ( p = line ; * p ; p + + ) {
fputc ( * p , fp ) ;
2024-01-03 22:02:43 +01:00
/* YAJL formats empty objects and arrays in a weird way:
*
* {
* " emptyarray " : [
*
* ] ,
* " emptyobject " : {
*
* }
* }
*
* We want to use empty lines to separate commands and replies as
* well as be compatible with python ' s ' json . dump ' method , thus we drop
* any whitespace between array / object braces .
*/
if ( ( p [ 0 ] = = ' { ' | | p [ 0 ] = = ' [ ' ) & & p [ 1 ] = = ' \n ' ) {
const char * l = p + 1 ;
while ( * l & & g_ascii_isspace ( * l ) )
l + + ;
if ( * l = = ' } ' | | * l = = ' ] ' )
p = l - 1 ;
}
2018-05-03 17:34:43 +02:00
}
}
2021-03-11 08:16:13 +01:00
static int ( * realQemuMonitorSend ) ( qemuMonitor * mon ,
qemuMonitorMessage * msg ) ;
2016-04-26 15:04:55 +02:00
int
2021-03-11 08:16:13 +01:00
qemuMonitorSend ( qemuMonitor * mon ,
qemuMonitorMessage * msg )
2016-04-26 15:04:55 +02:00
{
2021-09-04 22:33:55 +02:00
g_autofree char * reformatted = NULL ;
2018-05-03 17:29:36 +02:00
2016-04-26 15:04:55 +02:00
REAL_SYM ( realQemuMonitorSend ) ;
2018-05-03 17:29:36 +02:00
if ( ! ( reformatted = virJSONStringReformat ( msg - > txBuffer , true ) ) ) {
fprintf ( stderr , " Failed to reformat command string '%s' \n " , msg - > txBuffer ) ;
abort ( ) ;
}
if ( first )
first = false ;
else
printLineSkipEmpty ( " \n " , stdout ) ;
printLineSkipEmpty ( reformatted , stdout ) ;
2016-04-26 15:04:55 +02:00
return realQemuMonitorSend ( mon , msg ) ;
}
2021-03-11 08:16:13 +01:00
static int ( * realQemuMonitorJSONIOProcessLine ) ( qemuMonitor * mon ,
2016-04-26 15:04:55 +02:00
const char * line ,
2021-03-11 08:16:13 +01:00
qemuMonitorMessage * msg ) ;
2016-04-26 15:04:55 +02:00
int
2021-03-11 08:16:13 +01:00
qemuMonitorJSONIOProcessLine ( qemuMonitor * mon ,
2016-04-26 15:04:55 +02:00
const char * line ,
2021-03-11 08:16:13 +01:00
qemuMonitorMessage * msg )
2016-04-26 15:04:55 +02:00
{
2021-09-03 22:45:48 +02:00
g_autoptr ( virJSONValue ) value = NULL ;
2021-09-04 22:33:55 +02:00
g_autofree char * json = NULL ;
2016-04-26 15:04:55 +02:00
int ret ;
REAL_SYM ( realQemuMonitorJSONIOProcessLine ) ;
ret = realQemuMonitorJSONIOProcessLine ( mon , line , msg ) ;
2018-05-04 15:34:41 +02:00
if ( ret = = 0 ) {
if ( ! ( value = virJSONValueFromString ( line ) ) | |
! ( json = virJSONValueToString ( value , true ) ) ) {
fprintf ( stderr , " Failed to reformat reply string '%s' \n " , line ) ;
abort ( ) ;
}
2016-04-26 15:04:55 +02:00
2018-05-03 17:29:36 +02:00
/* Ignore QMP greeting */
if ( virJSONValueObjectHasKey ( value , " QMP " ) )
2021-09-04 22:38:39 +02:00
return 0 ;
2018-05-03 17:29:36 +02:00
if ( first )
2016-06-10 17:15:25 +02:00
first = false ;
2018-05-03 17:29:36 +02:00
else
printLineSkipEmpty ( " \n " , stdout ) ;
2016-06-10 17:15:25 +02:00
2018-05-03 17:34:43 +02:00
printLineSkipEmpty ( json , stdout ) ;
2016-04-26 15:04:55 +02:00
}
return ret ;
}