2008-09-08 19:59:00 +04:00
/*
2008-09-10 04:40:42 +04:00
* libudev - interface to udev device information
2008-09-08 19:59:00 +04:00
*
2008-09-10 04:40:42 +04:00
* Copyright ( C ) 2008 Kay Sievers < kay . sievers @ vrfy . org >
2008-09-08 19:59:00 +04:00
*
2009-03-26 21:29:36 +03:00
* 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 .
2008-09-08 19:59:00 +04:00
*/
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <stddef.h>
# include <string.h>
# include <unistd.h>
# include <sys/types.h>
2011-04-13 03:17:09 +04:00
# include <sys/poll.h>
2008-09-08 19:59:00 +04:00
# include <sys/socket.h>
# include <sys/un.h>
2011-07-11 03:16:32 +04:00
# include "udev.h"
2008-09-08 19:59:00 +04:00
2009-04-19 05:25:04 +04:00
/* wire protocol magic must match */
2008-10-17 19:32:17 +04:00
# define UDEV_CTRL_MAGIC 0xdead1dea
2008-09-08 19:59:00 +04:00
enum udev_ctrl_msg_type {
UDEV_CTRL_UNKNOWN ,
UDEV_CTRL_SET_LOG_LEVEL ,
UDEV_CTRL_STOP_EXEC_QUEUE ,
UDEV_CTRL_START_EXEC_QUEUE ,
UDEV_CTRL_RELOAD_RULES ,
UDEV_CTRL_SET_ENV ,
2010-05-27 19:27:56 +04:00
UDEV_CTRL_SET_CHILDREN_MAX ,
2011-04-13 03:17:09 +04:00
UDEV_CTRL_PING ,
UDEV_CTRL_EXIT ,
2008-09-08 19:59:00 +04:00
} ;
2008-10-17 19:32:17 +04:00
struct udev_ctrl_msg_wire {
char version [ 16 ] ;
unsigned int magic ;
2008-09-08 19:59:00 +04:00
enum udev_ctrl_msg_type type ;
union {
int intval ;
char buf [ 256 ] ;
} ;
} ;
struct udev_ctrl_msg {
int refcount ;
2011-04-13 03:17:09 +04:00
struct udev_ctrl_connection * conn ;
2008-10-17 19:32:17 +04:00
struct udev_ctrl_msg_wire ctrl_msg_wire ;
2008-09-08 19:59:00 +04:00
} ;
struct udev_ctrl {
int refcount ;
struct udev * udev ;
int sock ;
struct sockaddr_un saddr ;
socklen_t addrlen ;
2011-04-15 01:46:44 +04:00
bool bound ;
2011-10-10 00:52:03 +04:00
bool cleanup_socket ;
2011-04-13 03:17:09 +04:00
bool connected ;
} ;
struct udev_ctrl_connection {
int refcount ;
struct udev_ctrl * uctrl ;
int sock ;
2008-09-08 19:59:00 +04:00
} ;
2011-10-10 00:52:03 +04:00
struct udev_ctrl * udev_ctrl_new_from_fd ( struct udev * udev , int fd )
2008-09-08 19:59:00 +04:00
{
struct udev_ctrl * uctrl ;
2008-10-21 14:10:32 +04:00
uctrl = calloc ( 1 , sizeof ( struct udev_ctrl ) ) ;
2008-09-08 19:59:00 +04:00
if ( uctrl = = NULL )
return NULL ;
uctrl - > refcount = 1 ;
uctrl - > udev = udev ;
2011-04-15 01:46:44 +04:00
if ( fd < 0 ) {
2011-04-15 03:14:10 +04:00
uctrl - > sock = socket ( AF_LOCAL , SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0 ) ;
2011-04-15 01:46:44 +04:00
if ( uctrl - > sock < 0 ) {
err ( udev , " error getting socket: %m \n " ) ;
udev_ctrl_unref ( uctrl ) ;
return NULL ;
}
} else {
uctrl - > bound = true ;
uctrl - > sock = fd ;
2008-09-08 19:59:00 +04:00
}
uctrl - > saddr . sun_family = AF_LOCAL ;
2011-10-10 00:52:03 +04:00
util_strscpyl ( uctrl - > saddr . sun_path , sizeof ( uctrl - > saddr . sun_path ) ,
udev_get_run_path ( udev ) , " /control " , NULL ) ;
2008-09-08 19:59:00 +04:00
uctrl - > addrlen = offsetof ( struct sockaddr_un , sun_path ) + strlen ( uctrl - > saddr . sun_path ) ;
2011-03-23 18:40:23 +03:00
return uctrl ;
}
2011-10-10 00:52:03 +04:00
struct udev_ctrl * udev_ctrl_new ( struct udev * udev )
2011-03-23 18:40:23 +03:00
{
2011-10-10 00:52:03 +04:00
return udev_ctrl_new_from_fd ( udev , - 1 ) ;
2008-09-08 19:59:00 +04:00
}
int udev_ctrl_enable_receiving ( struct udev_ctrl * uctrl )
{
int err ;
2011-03-23 18:40:23 +03:00
2011-04-15 01:46:44 +04:00
if ( ! uctrl - > bound ) {
2011-03-23 18:40:23 +03:00
err = bind ( uctrl - > sock , ( struct sockaddr * ) & uctrl - > saddr , uctrl - > addrlen ) ;
2011-10-10 00:52:03 +04:00
if ( err < 0 & & errno = = EADDRINUSE ) {
unlink ( uctrl - > saddr . sun_path ) ;
err = bind ( uctrl - > sock , ( struct sockaddr * ) & uctrl - > saddr , uctrl - > addrlen ) ;
}
2011-03-23 18:40:23 +03:00
if ( err < 0 ) {
2011-04-13 03:17:09 +04:00
err = - errno ;
2011-03-23 18:40:23 +03:00
err ( uctrl - > udev , " bind failed: %m \n " ) ;
return err ;
}
2011-04-15 01:46:44 +04:00
2011-04-13 03:17:09 +04:00
err = listen ( uctrl - > sock , 0 ) ;
if ( err < 0 ) {
err = - errno ;
err ( uctrl - > udev , " listen failed: %m \n " ) ;
return err ;
}
2011-04-15 01:46:44 +04:00
uctrl - > bound = true ;
2011-10-10 00:52:03 +04:00
uctrl - > cleanup_socket = true ;
2008-09-08 19:59:00 +04:00
}
return 0 ;
}
struct udev * udev_ctrl_get_udev ( struct udev_ctrl * uctrl )
{
return uctrl - > udev ;
}
struct udev_ctrl * udev_ctrl_ref ( struct udev_ctrl * uctrl )
{
if ( uctrl = = NULL )
return NULL ;
uctrl - > refcount + + ;
return uctrl ;
}
2011-04-13 03:17:09 +04:00
struct udev_ctrl * udev_ctrl_unref ( struct udev_ctrl * uctrl )
2008-09-08 19:59:00 +04:00
{
if ( uctrl = = NULL )
2011-04-13 03:17:09 +04:00
return NULL ;
2008-09-08 19:59:00 +04:00
uctrl - > refcount - - ;
if ( uctrl - > refcount > 0 )
2011-04-13 03:17:09 +04:00
return uctrl ;
2008-09-08 19:59:00 +04:00
if ( uctrl - > sock > = 0 )
close ( uctrl - > sock ) ;
free ( uctrl ) ;
2011-04-13 03:17:09 +04:00
return NULL ;
2008-09-08 19:59:00 +04:00
}
2011-10-10 02:38:56 +04:00
int udev_ctrl_cleanup ( struct udev_ctrl * uctrl )
{
2011-10-10 04:30:42 +04:00
if ( uctrl = = NULL )
return 0 ;
2011-10-10 02:38:56 +04:00
if ( uctrl - > cleanup_socket )
unlink ( uctrl - > saddr . sun_path ) ;
return 0 ;
}
2008-09-08 19:59:00 +04:00
int udev_ctrl_get_fd ( struct udev_ctrl * uctrl )
{
if ( uctrl = = NULL )
2011-10-10 04:30:42 +04:00
return - EINVAL ;
2008-09-08 19:59:00 +04:00
return uctrl - > sock ;
}
2011-04-13 03:17:09 +04:00
struct udev_ctrl_connection * udev_ctrl_get_connection ( struct udev_ctrl * uctrl )
{
struct udev_ctrl_connection * conn ;
2011-05-20 00:57:46 +04:00
struct ucred ucred ;
socklen_t slen ;
2011-04-13 03:17:09 +04:00
const int on = 1 ;
conn = calloc ( 1 , sizeof ( struct udev_ctrl_connection ) ) ;
if ( conn = = NULL )
return NULL ;
conn - > refcount = 1 ;
conn - > uctrl = uctrl ;
2011-05-05 21:17:09 +04:00
conn - > sock = accept4 ( uctrl - > sock , NULL , NULL , SOCK_CLOEXEC | SOCK_NONBLOCK ) ;
2011-04-13 03:17:09 +04:00
if ( conn - > sock < 0 ) {
2011-05-05 21:17:09 +04:00
if ( errno ! = EINTR )
err ( uctrl - > udev , " unable to receive ctrl connection: %m \n " ) ;
2011-05-20 00:57:46 +04:00
goto err ;
}
/* check peer credential of connection */
slen = sizeof ( ucred ) ;
if ( getsockopt ( conn - > sock , SOL_SOCKET , SO_PEERCRED , & ucred , & slen ) < 0 ) {
err ( uctrl - > udev , " unable to receive credentials of ctrl connection: %m \n " ) ;
goto err ;
}
if ( ucred . uid > 0 ) {
err ( uctrl - > udev , " sender uid=%i, message ignored \n " , ucred . uid ) ;
goto err ;
2011-04-13 03:17:09 +04:00
}
2011-05-20 00:57:46 +04:00
/* enable receiving of the sender credentials in the messages */
2011-04-13 03:17:09 +04:00
setsockopt ( conn - > sock , SOL_SOCKET , SO_PASSCRED , & on , sizeof ( on ) ) ;
udev_ctrl_ref ( uctrl ) ;
return conn ;
2011-05-20 00:57:46 +04:00
err :
if ( conn - > sock > = 0 )
close ( conn - > sock ) ;
free ( conn ) ;
return NULL ;
2011-04-13 03:17:09 +04:00
}
struct udev_ctrl_connection * udev_ctrl_connection_ref ( struct udev_ctrl_connection * conn )
{
if ( conn = = NULL )
return NULL ;
conn - > refcount + + ;
return conn ;
}
struct udev_ctrl_connection * udev_ctrl_connection_unref ( struct udev_ctrl_connection * conn )
{
if ( conn = = NULL )
return NULL ;
conn - > refcount - - ;
if ( conn - > refcount > 0 )
return conn ;
if ( conn - > sock > = 0 )
close ( conn - > sock ) ;
udev_ctrl_unref ( conn - > uctrl ) ;
free ( conn ) ;
return NULL ;
}
static int ctrl_send ( struct udev_ctrl * uctrl , enum udev_ctrl_msg_type type , int intval , const char * buf , int timeout )
2008-09-08 19:59:00 +04:00
{
2008-10-17 19:32:17 +04:00
struct udev_ctrl_msg_wire ctrl_msg_wire ;
2011-04-13 03:17:09 +04:00
int err = 0 ;
2008-09-08 19:59:00 +04:00
2008-10-17 19:32:17 +04:00
memset ( & ctrl_msg_wire , 0x00 , sizeof ( struct udev_ctrl_msg_wire ) ) ;
strcpy ( ctrl_msg_wire . version , " udev- " VERSION ) ;
ctrl_msg_wire . magic = UDEV_CTRL_MAGIC ;
2008-09-16 05:01:15 +04:00
ctrl_msg_wire . type = type ;
2008-09-08 19:59:00 +04:00
if ( buf ! = NULL )
2009-05-20 19:57:52 +04:00
util_strscpy ( ctrl_msg_wire . buf , sizeof ( ctrl_msg_wire . buf ) , buf ) ;
2008-09-08 19:59:00 +04:00
else
2008-09-16 05:01:15 +04:00
ctrl_msg_wire . intval = intval ;
2008-09-08 19:59:00 +04:00
2011-04-13 03:17:09 +04:00
if ( ! uctrl - > connected ) {
if ( connect ( uctrl - > sock , ( struct sockaddr * ) & uctrl - > saddr , uctrl - > addrlen ) < 0 ) {
err = - errno ;
goto out ;
}
uctrl - > connected = true ;
}
if ( send ( uctrl - > sock , & ctrl_msg_wire , sizeof ( ctrl_msg_wire ) , 0 ) < 0 ) {
err = - errno ;
goto out ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
/* wait for peer message handling or disconnect */
for ( ; ; ) {
struct pollfd pfd [ 1 ] ;
int r ;
pfd [ 0 ] . fd = uctrl - > sock ;
pfd [ 0 ] . events = POLLIN ;
r = poll ( pfd , 1 , timeout * 1000 ) ;
if ( r < 0 ) {
if ( errno = = EINTR )
continue ;
err = - errno ;
break ;
}
if ( r > 0 & & pfd [ 0 ] . revents & POLLERR ) {
err = - EIO ;
break ;
}
if ( r = = 0 )
err = - ETIMEDOUT ;
break ;
}
out :
2008-09-08 19:59:00 +04:00
return err ;
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_set_log_level ( struct udev_ctrl * uctrl , int priority , int timeout )
{
return ctrl_send ( uctrl , UDEV_CTRL_SET_LOG_LEVEL , priority , NULL , timeout ) ;
}
int udev_ctrl_send_stop_exec_queue ( struct udev_ctrl * uctrl , int timeout )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_STOP_EXEC_QUEUE , 0 , NULL , timeout ) ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_start_exec_queue ( struct udev_ctrl * uctrl , int timeout )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_START_EXEC_QUEUE , 0 , NULL , timeout ) ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_reload_rules ( struct udev_ctrl * uctrl , int timeout )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_RELOAD_RULES , 0 , NULL , timeout ) ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_set_env ( struct udev_ctrl * uctrl , const char * key , int timeout )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_SET_ENV , 0 , key , timeout ) ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_set_children_max ( struct udev_ctrl * uctrl , int count , int timeout )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_SET_CHILDREN_MAX , count , NULL , timeout ) ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_ping ( struct udev_ctrl * uctrl , int timeout )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_PING , 0 , NULL , timeout ) ;
2008-09-08 19:59:00 +04:00
}
2011-04-13 03:17:09 +04:00
int udev_ctrl_send_exit ( struct udev_ctrl * uctrl , int timeout )
2009-03-10 16:00:16 +03:00
{
2011-04-13 03:17:09 +04:00
return ctrl_send ( uctrl , UDEV_CTRL_EXIT , 0 , NULL , timeout ) ;
2009-03-10 16:00:16 +03:00
}
2011-04-13 03:17:09 +04:00
struct udev_ctrl_msg * udev_ctrl_receive_msg ( struct udev_ctrl_connection * conn )
2008-09-08 19:59:00 +04:00
{
2011-04-13 03:17:09 +04:00
struct udev * udev = conn - > uctrl - > udev ;
2008-09-08 19:59:00 +04:00
struct udev_ctrl_msg * uctrl_msg ;
ssize_t size ;
struct msghdr smsg ;
struct cmsghdr * cmsg ;
struct iovec iov ;
struct ucred * cred ;
char cred_msg [ CMSG_SPACE ( sizeof ( struct ucred ) ) ] ;
2008-10-21 14:10:32 +04:00
uctrl_msg = calloc ( 1 , sizeof ( struct udev_ctrl_msg ) ) ;
2008-09-08 19:59:00 +04:00
if ( uctrl_msg = = NULL )
return NULL ;
uctrl_msg - > refcount = 1 ;
2011-04-13 03:17:09 +04:00
uctrl_msg - > conn = conn ;
2011-04-13 20:21:47 +04:00
udev_ctrl_connection_ref ( conn ) ;
2008-09-08 19:59:00 +04:00
2011-05-20 00:57:46 +04:00
/* wait for the incoming message */
for ( ; ; ) {
struct pollfd pfd [ 1 ] ;
int r ;
pfd [ 0 ] . fd = conn - > sock ;
pfd [ 0 ] . events = POLLIN ;
r = poll ( pfd , 1 , 10000 ) ;
if ( r < 0 ) {
if ( errno = = EINTR )
continue ;
goto err ;
} else if ( r = = 0 ) {
err ( udev , " timeout waiting for ctrl message \n " ) ;
goto err ;
} else {
if ( ! ( pfd [ 0 ] . revents & POLLIN ) ) {
err ( udev , " ctrl connection error: %m \n " ) ;
goto err ;
}
}
break ;
}
2008-09-16 05:01:15 +04:00
iov . iov_base = & uctrl_msg - > ctrl_msg_wire ;
2008-10-17 19:32:17 +04:00
iov . iov_len = sizeof ( struct udev_ctrl_msg_wire ) ;
2008-09-08 19:59:00 +04:00
memset ( & smsg , 0x00 , sizeof ( struct msghdr ) ) ;
smsg . msg_iov = & iov ;
smsg . msg_iovlen = 1 ;
smsg . msg_control = cred_msg ;
smsg . msg_controllen = sizeof ( cred_msg ) ;
2011-04-13 03:17:09 +04:00
size = recvmsg ( conn - > sock , & smsg , 0 ) ;
2008-09-08 19:59:00 +04:00
if ( size < 0 ) {
2011-05-20 00:57:46 +04:00
err ( udev , " unable to receive ctrl message: %m \n " ) ;
2008-09-08 19:59:00 +04:00
goto err ;
}
cmsg = CMSG_FIRSTHDR ( & smsg ) ;
cred = ( struct ucred * ) CMSG_DATA ( cmsg ) ;
if ( cmsg = = NULL | | cmsg - > cmsg_type ! = SCM_CREDENTIALS ) {
2011-04-13 03:17:09 +04:00
err ( udev , " no sender credentials received, message ignored \n " ) ;
2008-09-08 19:59:00 +04:00
goto err ;
}
if ( cred - > uid ! = 0 ) {
2011-04-13 03:17:09 +04:00
err ( udev , " sender uid=%i, message ignored \n " , cred - > uid ) ;
2008-09-08 19:59:00 +04:00
goto err ;
}
2008-10-17 19:32:17 +04:00
if ( uctrl_msg - > ctrl_msg_wire . magic ! = UDEV_CTRL_MAGIC ) {
2011-04-13 03:17:09 +04:00
err ( udev , " message magic 0x%08x doesn't match, ignore it \n " , uctrl_msg - > ctrl_msg_wire . magic ) ;
2008-09-08 19:59:00 +04:00
goto err ;
}
2011-04-13 03:17:09 +04:00
dbg ( udev , " created ctrl_msg %p (%i) \n " , uctrl_msg , uctrl_msg - > ctrl_msg_wire . type ) ;
2008-09-08 19:59:00 +04:00
return uctrl_msg ;
err :
udev_ctrl_msg_unref ( uctrl_msg ) ;
return NULL ;
}
struct udev_ctrl_msg * udev_ctrl_msg_ref ( struct udev_ctrl_msg * ctrl_msg )
{
if ( ctrl_msg = = NULL )
return NULL ;
ctrl_msg - > refcount + + ;
return ctrl_msg ;
}
2011-04-13 03:17:09 +04:00
struct udev_ctrl_msg * udev_ctrl_msg_unref ( struct udev_ctrl_msg * ctrl_msg )
2008-09-08 19:59:00 +04:00
{
if ( ctrl_msg = = NULL )
2011-04-13 03:17:09 +04:00
return NULL ;
2008-09-08 19:59:00 +04:00
ctrl_msg - > refcount - - ;
if ( ctrl_msg - > refcount > 0 )
2011-04-13 03:17:09 +04:00
return ctrl_msg ;
dbg ( ctrl_msg - > conn - > uctrl - > udev , " release ctrl_msg %p \n " , ctrl_msg ) ;
udev_ctrl_connection_unref ( ctrl_msg - > conn ) ;
2008-09-08 19:59:00 +04:00
free ( ctrl_msg ) ;
2011-04-13 03:17:09 +04:00
return NULL ;
2008-09-08 19:59:00 +04:00
}
int udev_ctrl_get_set_log_level ( struct udev_ctrl_msg * ctrl_msg )
{
2008-09-16 05:01:15 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_SET_LOG_LEVEL )
return ctrl_msg - > ctrl_msg_wire . intval ;
2008-09-08 19:59:00 +04:00
return - 1 ;
}
int udev_ctrl_get_stop_exec_queue ( struct udev_ctrl_msg * ctrl_msg )
{
2008-09-16 05:01:15 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_STOP_EXEC_QUEUE )
2008-09-08 19:59:00 +04:00
return 1 ;
return - 1 ;
}
int udev_ctrl_get_start_exec_queue ( struct udev_ctrl_msg * ctrl_msg )
{
2008-09-16 05:01:15 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_START_EXEC_QUEUE )
2008-09-08 19:59:00 +04:00
return 1 ;
return - 1 ;
}
int udev_ctrl_get_reload_rules ( struct udev_ctrl_msg * ctrl_msg )
{
2008-09-16 05:01:15 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_RELOAD_RULES )
2008-09-08 19:59:00 +04:00
return 1 ;
return - 1 ;
}
const char * udev_ctrl_get_set_env ( struct udev_ctrl_msg * ctrl_msg )
{
2008-09-16 05:01:15 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_SET_ENV )
return ctrl_msg - > ctrl_msg_wire . buf ;
2008-09-08 19:59:00 +04:00
return NULL ;
}
2010-05-27 19:27:56 +04:00
int udev_ctrl_get_set_children_max ( struct udev_ctrl_msg * ctrl_msg )
2008-09-08 19:59:00 +04:00
{
2010-05-27 19:27:56 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_SET_CHILDREN_MAX )
2008-09-16 05:01:15 +04:00
return ctrl_msg - > ctrl_msg_wire . intval ;
2008-09-08 19:59:00 +04:00
return - 1 ;
}
2009-03-10 16:00:16 +03:00
2011-04-13 03:17:09 +04:00
int udev_ctrl_get_ping ( struct udev_ctrl_msg * ctrl_msg )
2009-03-10 16:00:16 +03:00
{
2011-04-13 03:17:09 +04:00
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_PING )
return 1 ;
return - 1 ;
}
int udev_ctrl_get_exit ( struct udev_ctrl_msg * ctrl_msg )
{
if ( ctrl_msg - > ctrl_msg_wire . type = = UDEV_CTRL_EXIT )
return 1 ;
2009-03-10 16:00:16 +03:00
return - 1 ;
}