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.
30 #include <sys/types.h>
33 #include <sys/socket.h>
39 #include "udev_version.h"
45 void log_message (int level, const char *format, ...)
49 va_start(args, format);
50 vsyslog(level, format, args);
58 * Scan a file, write all variables into the msgbuf and
59 * fires the message to udevd.
61 static int udevsend(char *filename, int sock, int disable_loop_detection)
63 static struct udevd_msg usend_msg;
68 char *fdmap, *ls, *le, *ch;
69 struct sockaddr_un saddr;
73 if (stat(filename,&statbuf) < 0) {
74 dbg("cannot stat %s: %s\n", filename, strerror(errno));
77 fd = open(filename,O_RDONLY);
81 fdmap = mmap(0, statbuf.st_size,
82 PROT_READ, MAP_PRIVATE, fd, 0);
84 if (fdmap == MAP_FAILED) {
85 dbg("mmap failed, errno %d\n", errno);
89 memset(&saddr, 0x00, sizeof(struct sockaddr_un));
90 saddr.sun_family = AF_LOCAL;
91 /* use abstract namespace for socket path */
92 strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
93 addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
95 memset(&usend_msg, 0x00, sizeof(struct udevd_msg));
96 strcpy(usend_msg.magic, UDEV_MAGIC);
97 usend_msg.type = UDEVD_INITSEND;
101 while (*ch && ch < fdmap + statbuf.st_size) {
102 le = strchr(ch, '\n');
105 ch = strchr(ch, '=');
109 /* prevent loops in the scripts we execute */
110 if (strncmp(ls, "UDEVD_EVENT=", 12) == 0) {
111 if (!disable_loop_detection) {
112 dbg("event already handled by udev\n");
119 /* omit shell-generated keys */
120 if (ls[0] == '_' && ls[1] == '=') {
126 strncpy(&usend_msg.envbuf[bufpos],ls,(ch - ls) + 1);
127 bufpos += (ch - ls) + 1;
128 if (ch[1] == '\'' && le[-1] == '\'') {
129 strncpy(&usend_msg.envbuf[bufpos],ch + 2, (le - ch) -3);
130 bufpos += (le - ch) - 3;
132 strncpy(&usend_msg.envbuf[bufpos],ch, (le - ch));
141 munmap(fdmap, statbuf.st_size);
143 usend_msg_len = offsetof(struct udevd_msg, envbuf) + bufpos;
144 dbg("usend_msg_len=%i", usend_msg_len);
147 retval = sendto(sock, &usend_msg, usend_msg_len, 0, (struct sockaddr *)&saddr, addrlen);
149 dbg("error sending message (%s)", strerror(errno));
156 int main(int argc, char *argv[], char *envp[])
158 static const char short_options[] = "d:f:lVh";
160 char *event_dir = NULL;
161 char *event_file = NULL;
163 struct dirent *direntry;
165 int disable_loop_detection = 0;
168 logging_init("udevinitsend");
169 dbg("version %s", UDEV_VERSION);
171 /* get command line options */
173 option = getopt(argc, argv, short_options);
177 dbg("option '%c': ", option);
180 dbg("scan directory %s\n", optarg);
185 dbg("use event file %s\n", optarg);
190 dbg("disable loop detection, ignore UDEVD_EVENT\n");
191 disable_loop_detection = 1;
199 sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
201 dbg("error getting socket");
206 dirstream = opendir(event_dir);
208 info("error opening directory %s: %s\n",
209 event_dir, strerror(errno));
213 while ((direntry = readdir(dirstream)) != NULL) {
214 if (!strcmp(direntry->d_name,".") ||
215 !strcmp(direntry->d_name,".."))
217 retval = udevsend(direntry->d_name, sock, disable_loop_detection);
220 } else if (event_file) {
221 retval = udevsend(event_file, sock, disable_loop_detection);