6 * Copyright (C) 2004 Ling, Xiaofeng <xiaofeng.ling@intel.com>
7 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation version 2 of the License.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sys/types.h>
40 #define BUFFER_SIZE 1024
41 #define EVENT_TIMEOUT_SECONDS 10
42 #define DAEMON_TIMEOUT_SECONDS 30
45 static int expect_seqnum = 0;
46 static struct hotplug_msg *head = NULL;
49 static void sig_alarmhandler(int signum)
51 dbg("caught signal %d", signum);
54 dbg("event timeout reached");
58 dbg("unhandled signal");
62 static void dump_queue(void)
64 struct hotplug_msg *p;
67 dbg("next expected sequence is %d", expect_seqnum);
69 dbg("sequence %d in queue", p->seqnum);
74 static void dump_msg(struct hotplug_msg *pmsg)
76 dbg("sequence %d, '%s', '%s', '%s'",
77 pmsg->seqnum, pmsg->action, pmsg->devpath, pmsg->subsystem);
80 static int dispatch_msg(struct hotplug_msg *pmsg)
84 extern char **environ;
88 setenv("ACTION", pmsg->action, 1);
89 setenv("DEVPATH", pmsg->devpath, 1);
90 argv[0] = DEFAULT_UDEV_EXEC;
91 argv[1] = pmsg->subsystem;
98 execve(argv[0], argv, environ);
99 dbg("exec of child failed");
103 dbg("fork of child failed");
111 static void set_timer(int seconds)
113 signal(SIGALRM, sig_alarmhandler);
117 static void check_queue(void)
119 struct hotplug_msg *p;
123 while(head != NULL && head->seqnum == expect_seqnum) {
131 set_timer(EVENT_TIMEOUT_SECONDS);
133 set_timer(DAEMON_TIMEOUT_SECONDS);
136 static void add_queue(struct hotplug_msg *pmsg)
138 struct hotplug_msg *pnewmsg;
139 struct hotplug_msg *p;
140 struct hotplug_msg *p1;
144 pnewmsg = malloc(sizeof(struct hotplug_msg));
146 pnewmsg->next = NULL;
147 while(p != NULL && pmsg->seqnum > p->seqnum) {
160 static int process_queue(void)
164 struct hotplug_msg *pmsg;
165 char buf[BUFFER_SIZE];
168 key = ftok(DEFAULT_UDEVD_EXEC, IPC_KEY_ID);
169 pmsg = (struct hotplug_msg *) buf;
170 msgid = msgget(key, IPC_CREAT);
172 dbg("open message queue error");
176 ret = msgrcv(msgid, (struct msgbuf *) buf, BUFFER_SIZE-4, HOTPLUGMSGTYPE, 0);
178 dbg("current sequence %d, expected sequence %d", pmsg->seqnum, expect_seqnum);
180 /* init expected sequence with value from first call */
181 if (expect_seqnum == 0) {
182 expect_seqnum = pmsg->seqnum;
183 dbg("init next expected sequence number to %d", expect_seqnum);
186 if (pmsg->seqnum > expect_seqnum) {
188 set_timer(EVENT_TIMEOUT_SECONDS);
190 if (pmsg->seqnum == expect_seqnum) {
195 dbg("timeout event for unexpected sequence number %d", pmsg->seqnum);
199 if (errno == EINTR) {
201 /* event timeout, skip all missing, proceed with next queued event */
202 info("timeout reached, skip events %d - %d", expect_seqnum, head->seqnum-1);
203 expect_seqnum = head->seqnum;
205 info("we have nothing to do, so daemon exits...");
210 dbg("ipc message receive error '%s'", strerror(errno));
217 static void sig_handler(int signum)
219 dbg("caught signal %d", signum);
228 dbg("unhandled signal");
232 int main(int argc, char *argv[])
234 /* set up signal handler */
235 signal(SIGINT, sig_handler);
236 signal(SIGTERM, sig_handler);
237 signal(SIGKILL, sig_handler);
239 /* we exit if we have nothing to do, next event will start us again */
240 set_timer(DAEMON_TIMEOUT_SECONDS);