chiark / gitweb /
[PATCH] actually have udev run files ending in .dev in the /etc/dev.d/ directory...
[elogind.git] / dev_d.c
1 /*
2  * dev.d multipleer
3  * 
4  * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
5  *
6  *      This program is free software; you can redistribute it and/or modify it
7  *      under the terms of the GNU General Public License as published by the
8  *      Free Software Foundation version 2 of the License.
9  * 
10  * Based on the klibc version of hotplug written by:
11  *      Author(s) Christian Borntraeger <cborntra@de.ibm.com>
12  * which was based on the shell script written by:
13  *      Greg Kroah-Hartman <greg@kroah.com>
14  *
15  */
16
17 /* 
18  * This essentially emulates the following shell script logic in C:
19         DIR="/etc/dev.d"
20         export DEVNODE="whatever_dev_name_udev_just_gave"
21         for I in "${DIR}/$DEVNODE/"*.dev "${DIR}/$1/"*.dev "${DIR}/default/"*.dev ; do
22                 if [ -f $I ]; then $I $1 ; fi
23         done
24         exit 1;
25  */
26
27 #include <dirent.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <unistd.h>
34 #include "udev.h"
35 #include "udev_lib.h"
36 #include "logging.h"
37
38 #define HOTPLUGDIR      "/etc/dev.d"
39 #define SUFFIX          ".dev" 
40 #define COMMENT_PREFIX  '#'
41
42 static void run_program(char *name)
43 {
44         pid_t pid;
45
46         dbg("running %s", name);
47
48         pid = fork();
49
50         if (pid < 0) {
51                 perror("fork");
52                 return;
53         } 
54         
55         if (pid > 0) {
56                 wait(NULL);
57                 return;
58         }
59
60         execv(name, main_argv);
61         exit(1);
62 }
63
64 static void execute_dir (char *dirname)
65 {
66         DIR *directory;
67         struct dirent *entry;
68         char filename[NAME_SIZE];
69         int name_len;
70
71         dbg("opening %s", dirname);
72         directory = opendir(dirname);
73         if (!directory)
74                 return;
75
76         while ((entry = readdir(directory))) {
77                 if (entry->d_name[0] == '\0')
78                         break;
79                 /* Don't run the files '.', '..', or hidden files, 
80                  * or files that start with a '#' */
81                 if ((entry->d_name[0] == '.') ||
82                     (entry->d_name[0] == COMMENT_PREFIX))
83                         continue;
84
85                 /* Nor do we run files that do not end in ".dev" */
86                 name_len = strlen(entry->d_name);
87                 if (name_len < strlen(SUFFIX))
88                         continue;
89                 if (strcmp(&entry->d_name[name_len - sizeof (SUFFIX) + 1], SUFFIX) != 0)
90                         continue;
91
92                 /* FIXME - need to use file_list_insert() here to run these in sorted order... */
93                 snprintf(filename, sizeof(filename), "%s%s", dirname, entry->d_name);
94                 filename[sizeof(filename)-1] = '\0';
95                 run_program(filename);
96         }
97
98         closedir(directory);
99 }
100
101 /* runs files in these directories in order:
102  *      name given by udev
103  *      subsystem
104  *      default
105  */
106 void dev_d_send(struct udevice *dev, char *subsystem)
107 {
108         char dirname[256];
109         char devnode[NAME_SIZE];
110
111         strfieldcpy(devnode, udev_root);
112         strfieldcat(devnode, dev->name);
113         setenv("DEVNODE", devnode, 1);
114
115         snprintf(dirname, sizeof(dirname), HOTPLUGDIR "/%s/", dev->name);
116         dirname[sizeof(dirname)-1] = '\0';
117         execute_dir(dirname);
118
119         snprintf(dirname, sizeof(dirname), HOTPLUGDIR "/%s/", subsystem);
120         dirname[sizeof(dirname)-1] = '\0';
121         execute_dir(dirname);
122
123         strcpy(dirname, HOTPLUGDIR "/default/");
124         execute_dir(dirname);
125 }
126