6 * Copyright (C) 2004, 2005 Hannes Reinecke <hare@suse.de>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation version 2 of the License.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include <sys/types.h>
34 #include <sys/socket.h>
40 #include "udev_version.h"
42 #include "udev_utils.h"
48 void log_message (int priority, const char *format, ...)
55 va_start(args, format);
56 vsyslog(priority, format, args);
64 * Scan a file, write all variables into the msgbuf and
65 * fires the message to udevd.
67 static int udevsend(char *filename, int sock, int disable_loop_detection)
69 static struct udevd_msg usend_msg;
74 char *fdmap, *ls, *le, *ch;
75 struct sockaddr_un saddr;
79 if (stat(filename,&statbuf) < 0) {
80 dbg("cannot stat %s: %s\n", filename, strerror(errno));
83 fd = open(filename,O_RDONLY);
87 fdmap = mmap(0, statbuf.st_size,
88 PROT_READ, MAP_PRIVATE, fd, 0);
90 if (fdmap == MAP_FAILED) {
91 dbg("mmap failed, errno %d\n", errno);
95 memset(&saddr, 0x00, sizeof(struct sockaddr_un));
96 saddr.sun_family = AF_LOCAL;
97 /* use abstract namespace for socket path */
98 strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
99 addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
101 memset(&usend_msg, 0x00, sizeof(struct udevd_msg));
102 strcpy(usend_msg.magic, UDEV_MAGIC);
103 usend_msg.type = UDEVD_UEVENT_INITSEND;
107 while (*ch && ch < fdmap + statbuf.st_size) {
108 le = strchr(ch, '\n');
111 ch = strchr(ch, '=');
115 /* prevent loops in the scripts we execute */
116 if (strncmp(ls, "UDEVD_EVENT=", 12) == 0) {
117 if (!disable_loop_detection) {
118 dbg("event already handled by udev\n");
125 /* omit shell-generated keys */
126 if (ls[0] == '_' && ls[1] == '=') {
132 strncpy(&usend_msg.envbuf[bufpos],ls,(ch - ls) + 1);
133 bufpos += (ch - ls) + 1;
134 if (ch[1] == '\'' && le[-1] == '\'') {
135 strncpy(&usend_msg.envbuf[bufpos],ch + 2, (le - ch) - 3);
136 bufpos += (le - ch) - 3;
138 strncpy(&usend_msg.envbuf[bufpos],ch + 1, (le - ch) - 1);
139 bufpos += (le - ch) - 1;
147 munmap(fdmap, statbuf.st_size);
149 usend_msg_len = offsetof(struct udevd_msg, envbuf) + bufpos;
150 dbg("usend_msg_len=%i", usend_msg_len);
153 retval = sendto(sock, &usend_msg, usend_msg_len, 0, (struct sockaddr *)&saddr, addrlen);
155 dbg("error sending message (%s)", strerror(errno));
162 int main(int argc, char *argv[], char *envp[])
164 static const char short_options[] = "d:f:lVh";
166 char *event_dir = NULL;
167 char *event_file = NULL;
169 struct dirent *direntry;
171 int disable_loop_detection = 0;
175 env = getenv("UDEV_LOG");
177 log = log_priority(env);
179 logging_init("udevinitsend");
180 dbg("version %s", UDEV_VERSION);
182 /* get command line options */
184 option = getopt(argc, argv, short_options);
188 dbg("option '%c': ", option);
191 dbg("scan directory %s\n", optarg);
196 dbg("use event file %s\n", optarg);
201 dbg("disable loop detection, ignore UDEVD_EVENT\n");
202 disable_loop_detection = 1;
210 sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
212 dbg("error getting socket");
217 dirstream = opendir(event_dir);
219 info("error opening directory %s: %s\n",
220 event_dir, strerror(errno));
224 while ((direntry = readdir(dirstream)) != NULL) {
225 if (!strcmp(direntry->d_name,".") ||
226 !strcmp(direntry->d_name,".."))
228 retval = udevsend(direntry->d_name, sock, disable_loop_detection);
231 } else if (event_file) {
232 retval = udevsend(event_file, sock, disable_loop_detection);