2004-03-25 07:46:58 +03:00
/*
2004-11-25 04:44:38 +03:00
* udev_multiplex . c directory multiplexer
2004-03-25 07:46:58 +03:00
*
* Copyright ( C ) 2004 Greg Kroah - Hartman < greg @ kroah . com >
*
* 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 version 2 of the License .
*/
2004-03-27 12:21:46 +03:00
/*
2004-03-25 07:46:58 +03:00
* This essentially emulates the following shell script logic in C :
2004-03-27 12:21:46 +03:00
* DIR = " /etc/dev.d "
2004-04-09 05:48:56 +04:00
* export DEVNAME = " whatever_dev_name_udev_just_gave "
* for I in " ${DIR}/$DEVNAME/ " * . dev " ${DIR}/$1/ " * . dev " ${DIR}/default/ " * . dev ; do
2004-03-27 12:21:46 +03:00
* if [ - f $ I ] ; then $ I $ 1 ; fi
* done
* exit 1 ;
2004-03-25 07:46:58 +03:00
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/types.h>
# include <sys/wait.h>
2004-10-06 11:54:08 +04:00
# include <sys/stat.h>
2004-03-25 07:46:58 +03:00
# include <unistd.h>
2004-10-06 11:54:08 +04:00
# include <fcntl.h>
2004-03-25 07:46:58 +03:00
# include "udev.h"
2005-03-07 06:29:43 +03:00
# include "udev_libc_wrapper.h"
2004-11-25 04:44:38 +03:00
# include "udev_utils.h"
2004-03-25 07:46:58 +03:00
# include "logging.h"
2005-03-04 23:33:57 +03:00
static int run_program ( struct udevice * udev , const char * filename )
2004-03-25 07:46:58 +03:00
{
pid_t pid ;
2004-10-06 11:54:08 +04:00
int fd ;
2004-03-25 07:46:58 +03:00
2004-11-12 08:20:22 +03:00
dbg ( " running %s " , filename ) ;
2004-03-25 07:46:58 +03:00
pid = fork ( ) ;
2004-03-27 12:21:46 +03:00
switch ( pid ) {
case 0 :
/* child */
2004-10-06 11:54:08 +04:00
fd = open ( " /dev/null " , O_RDWR ) ;
if ( fd > = 0 ) {
dup2 ( fd , STDOUT_FILENO ) ;
dup2 ( fd , STDIN_FILENO ) ;
dup2 ( fd , STDERR_FILENO ) ;
}
close ( fd ) ;
2004-10-07 11:17:11 +04:00
2004-11-12 08:20:22 +03:00
execl ( filename , filename , udev - > subsystem , NULL ) ;
2004-03-27 12:21:46 +03:00
dbg ( " exec of child failed " ) ;
2004-10-19 06:28:39 +04:00
_exit ( 1 ) ;
2004-03-27 12:21:46 +03:00
case - 1 :
dbg ( " fork of child failed " ) ;
break ;
return - 1 ;
default :
2004-11-05 15:16:56 +03:00
waitpid ( pid , NULL , 0 ) ;
2004-03-25 07:46:58 +03:00
}
2004-03-27 12:21:46 +03:00
return 0 ;
2004-03-25 07:46:58 +03:00
}
2004-03-27 12:21:46 +03:00
/*
* runs files in these directories in order :
* < node name given by udev > /
* subsystem /
* default /
2004-03-25 07:46:58 +03:00
*/
2004-11-25 04:44:38 +03:00
void udev_multiplex_directory ( struct udevice * udev , const char * basedir , const char * suffix )
2004-03-25 07:46:58 +03:00
{
2005-03-07 06:29:43 +03:00
char dirname [ PATH_SIZE ] ;
2005-03-17 11:59:32 +03:00
struct name_entry * name_loop , * name_tmp ;
LIST_HEAD ( name_list ) ;
2004-04-22 07:24:51 +04:00
2004-11-12 08:21:16 +03:00
/* chop the device name up into pieces based on '/' */
2004-11-25 11:55:54 +03:00
if ( udev - > name [ 0 ] ! = ' \0 ' ) {
2005-03-07 06:29:43 +03:00
char devname [ PATH_SIZE ] ;
2004-11-25 11:55:54 +03:00
char * temp ;
2005-03-07 06:29:43 +03:00
strlcpy ( devname , udev - > name , sizeof ( devname ) ) ;
2004-11-25 11:55:54 +03:00
temp = strchr ( devname , ' / ' ) ;
while ( temp ! = NULL ) {
temp [ 0 ] = ' \0 ' ;
/* don't call the subsystem directory here */
if ( strcmp ( devname , udev - > subsystem ) ! = 0 ) {
2005-03-07 06:29:43 +03:00
snprintf ( dirname , sizeof ( dirname ) , " %s/%s " , basedir , devname ) ;
dirname [ sizeof ( dirname ) - 1 ] = ' \0 ' ;
2005-03-17 11:59:32 +03:00
add_matching_files ( & name_list , dirname , suffix ) ;
2004-11-25 11:55:54 +03:00
}
temp [ 0 ] = ' / ' ;
+ + temp ;
temp = strchr ( temp , ' / ' ) ;
}
2004-04-22 07:24:51 +04:00
}
2004-03-25 07:46:58 +03:00
2004-11-23 08:22:26 +03:00
if ( udev - > name [ 0 ] ! = ' \0 ' ) {
2005-03-07 06:29:43 +03:00
snprintf ( dirname , sizeof ( dirname ) , " %s/%s " , basedir , udev - > name ) ;
dirname [ sizeof ( dirname ) - 1 ] = ' \0 ' ;
2005-03-17 11:59:32 +03:00
add_matching_files ( & name_list , dirname , suffix ) ;
2004-11-23 08:22:26 +03:00
}
2004-03-25 07:46:58 +03:00
2004-11-23 08:22:26 +03:00
if ( udev - > subsystem [ 0 ] ! = ' \0 ' ) {
2005-03-07 06:29:43 +03:00
snprintf ( dirname , sizeof ( dirname ) , " %s/%s " , basedir , udev - > subsystem ) ;
dirname [ sizeof ( dirname ) - 1 ] = ' \0 ' ;
2005-03-17 11:59:32 +03:00
add_matching_files ( & name_list , dirname , suffix ) ;
2004-11-23 08:22:26 +03:00
}
2004-03-25 07:46:58 +03:00
2005-03-07 06:29:43 +03:00
snprintf ( dirname , sizeof ( dirname ) , " %s/default " , basedir ) ;
dirname [ sizeof ( dirname ) - 1 ] = ' \0 ' ;
2005-03-17 11:59:32 +03:00
add_matching_files ( & name_list , dirname , suffix ) ;
list_for_each_entry_safe ( name_loop , name_tmp , & name_list , node ) {
run_program ( udev , name_loop - > name ) ;
list_del ( & name_loop - > node ) ;
}
2004-03-25 07:46:58 +03:00
}