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 ignore_loops)
65 char *fdmap, *ls, *le, *ch;
66 struct udevd_msg usend_msg;
69 struct sockaddr_un saddr;
72 if (stat(filename,&statbuf) < 0) {
73 dbg("cannot stat %s: %s\n", filename, strerror(errno));
76 fd = open(filename,O_RDONLY);
80 fdmap = mmap(0, statbuf.st_size,
81 PROT_READ, MAP_PRIVATE, fd, 0);
83 if (fdmap == MAP_FAILED) {
84 dbg("mmap failed, errno %d\n", errno);
88 memset(&saddr, 0x00, sizeof(struct sockaddr_un));
89 saddr.sun_family = AF_LOCAL;
90 /* use abstract namespace for socket path */
91 strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
92 addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
94 memset(usend_msg.envbuf, 0, UEVENT_BUFFER_SIZE+256);
96 memset(&usend_msg, 0x00, sizeof(struct udevd_msg));
97 strcpy(usend_msg.magic, UDEV_MAGIC);
101 while (*ch && ch < fdmap + statbuf.st_size) {
102 le = strchr(ch,'\n');
109 /* prevent loops in the scripts we execute */
110 if (strncmp(ls, "UDEVD_EVENT=", 12) == 0) {
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;
164 int retval = 1, ignore_loops = 0;
167 logging_init("udevinitsend");
168 dbg("version %s", UDEV_VERSION);
170 /* get command line options */
172 option = getopt(argc, argv, short_options);
176 dbg("option '%c': ", option);
179 dbg("scan directory %s\n", optarg);
184 dbg("use event file %s\n", optarg);
189 dbg("ignoring loops\n");
194 printf("udevinitsend, version 0.1\n");
202 sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
204 dbg("error getting socket");
209 dirstream = opendir(event_dir);
211 info("error opening directory %s: %s\n",
212 event_dir, strerror(errno));
216 while ((direntry = readdir(dirstream)) != NULL) {
217 if (!strcmp(direntry->d_name,".") ||
218 !strcmp(direntry->d_name,".."))
220 retval = udevsend(direntry->d_name, sock, ignore_loops);
223 } else if (event_file) {
224 retval = udevsend(event_file, sock, ignore_loops);