2012-02-28 22:35:04 +04:00
/*
* Copyright ( C ) 2011 - 2012 Red Hat , Inc .
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2011-06-14 06:34:18 +04:00
# include "daemon-shared.h"
2012-02-28 22:35:04 +04:00
# include "daemon-client.h"
2011-06-14 06:34:18 +04:00
# include <sys/un.h>
# include <sys/socket.h>
# include <string.h>
# include <stdio.h>
2011-08-31 16:18:40 +04:00
# include <unistd.h>
2011-06-14 06:34:18 +04:00
# include <assert.h>
2011-06-27 17:14:53 +04:00
# include <errno.h> // ENOMEM
2011-06-14 06:34:18 +04:00
daemon_handle daemon_open ( daemon_info i ) {
2012-02-26 12:46:28 +04:00
daemon_handle h = { . protocol_version = 0 , . error = 0 } ;
2012-02-24 04:02:54 +04:00
daemon_reply r = { . cft = NULL } ;
2011-06-14 06:34:18 +04:00
struct sockaddr_un sockaddr ;
2011-09-17 18:49:18 +04:00
2012-02-26 12:46:28 +04:00
if ( ( h . socket_fd = socket ( PF_UNIX , SOCK_STREAM /* | SOCK_NONBLOCK */ , 0 ) ) < 0 )
2011-06-14 06:34:18 +04:00
goto error ;
2012-02-26 12:46:28 +04:00
2011-06-14 06:34:18 +04:00
memset ( & sockaddr , 0 , sizeof ( sockaddr ) ) ;
2012-04-10 16:55:37 +04:00
strncpy ( sockaddr . sun_path , i . socket , sizeof ( sockaddr . sun_path ) ) ;
2011-06-14 06:34:18 +04:00
sockaddr . sun_family = AF_UNIX ;
2012-02-26 12:46:28 +04:00
if ( connect ( h . socket_fd , ( struct sockaddr * ) & sockaddr , sizeof ( sockaddr ) ) )
2011-06-14 06:34:18 +04:00
goto error ;
2012-02-24 03:52:11 +04:00
2012-02-24 04:02:54 +04:00
r = daemon_send_simple ( h , " hello " , NULL ) ;
2012-02-24 03:52:11 +04:00
if ( r . error | | strcmp ( daemon_reply_str ( r , " response " , " unknown " ) , " OK " ) )
goto error ;
h . protocol = daemon_reply_str ( r , " protocol " , NULL ) ;
if ( h . protocol )
h . protocol = dm_strdup ( h . protocol ) ; /* keep around */
h . protocol_version = daemon_reply_int ( r , " version " , 0 ) ;
if ( i . protocol & & ( ! h . protocol | | strcmp ( h . protocol , i . protocol ) ) )
goto error ;
if ( i . protocol_version & & h . protocol_version ! = i . protocol_version )
goto error ;
daemon_reply_destroy ( r ) ;
2011-06-14 06:34:18 +04:00
return h ;
2012-02-26 12:46:28 +04:00
2011-06-14 06:34:18 +04:00
error :
2012-02-26 12:46:28 +04:00
h . error = errno ;
2011-06-14 06:34:18 +04:00
if ( h . socket_fd > = 0 )
2012-03-02 01:12:37 +04:00
if ( close ( h . socket_fd ) )
perror ( " close " ) ;
2012-02-24 03:52:11 +04:00
if ( r . cft )
daemon_reply_destroy ( r ) ;
2011-06-14 06:34:18 +04:00
h . socket_fd = - 1 ;
return h ;
}
daemon_reply daemon_send ( daemon_handle h , daemon_request rq )
{
2012-02-15 13:14:54 +04:00
daemon_reply reply = { . cft = NULL , . error = 0 } ;
2011-06-14 06:34:18 +04:00
assert ( h . socket_fd > = 0 ) ;
if ( ! rq . buffer ) {
/* TODO: build the buffer from rq.cft */
}
assert ( rq . buffer ) ;
2012-02-26 12:46:28 +04:00
if ( ! write_buffer ( h . socket_fd , rq . buffer , strlen ( rq . buffer ) ) )
reply . error = errno ;
2011-06-14 06:34:18 +04:00
if ( read_buffer ( h . socket_fd , & reply . buffer ) ) {
2011-08-30 19:42:56 +04:00
reply . cft = dm_config_from_string ( reply . buffer ) ;
2011-06-14 06:34:18 +04:00
} else
2012-02-26 12:46:28 +04:00
reply . error = errno ;
2011-06-14 06:34:18 +04:00
return reply ;
}
2011-06-27 17:58:11 +04:00
void daemon_reply_destroy ( daemon_reply r ) {
if ( r . cft )
2011-08-31 16:18:40 +04:00
dm_config_destroy ( r . cft ) ;
2012-02-24 03:52:11 +04:00
dm_free ( r . buffer ) ;
2011-06-27 17:58:11 +04:00
}
2012-01-15 19:16:50 +04:00
daemon_reply daemon_send_simple ( daemon_handle h , const char * id , . . . )
2011-06-27 17:14:53 +04:00
{
2011-09-17 18:49:18 +04:00
static const daemon_reply err = { . error = ENOMEM , . buffer = NULL , . cft = NULL } ;
2011-10-31 01:58:59 +04:00
daemon_request rq = { . cft = NULL } ;
2011-09-17 18:49:18 +04:00
daemon_reply repl ;
2011-06-27 17:14:53 +04:00
va_list ap ;
2011-09-17 18:49:18 +04:00
2011-06-27 17:14:53 +04:00
va_start ( ap , id ) ;
2011-09-17 18:49:18 +04:00
rq . buffer = format_buffer ( " request " , id , ap ) ;
va_end ( ap ) ;
2011-06-27 17:14:53 +04:00
2011-09-17 18:49:18 +04:00
if ( ! rq . buffer )
2011-06-27 17:14:53 +04:00
return err ;
2011-09-17 18:49:18 +04:00
repl = daemon_send ( h , rq ) ;
2012-02-27 15:49:16 +04:00
dm_free ( rq . buffer ) ;
2011-06-27 17:14:53 +04:00
return repl ;
}
void daemon_close ( daemon_handle h )
{
2012-02-24 03:52:11 +04:00
dm_free ( ( char * ) h . protocol ) ;
2011-06-14 06:34:18 +04:00
}