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 TIMEOUT_SECONDS 10
43 static void reset_timer(void);
44 static void reset_queue(void);
47 static int expect_seqnum = 0;
48 static int timeout_value = TIMEOUT_SECONDS;
49 static int timeout = 0;
50 static struct hotplug_msg *head = NULL;
51 static char exec_program[100];
54 static void sig_handler(int signum)
56 dbg("caught signal %d", signum);
59 dbg("reset requested, all waiting events killed");
73 dbg("unhandled signal");
77 static void sig_alarmhandler(int signum)
79 dbg("caught signal %d", signum);
83 dbg("event timeout reached");
87 dbg("unhandled signal");
91 static void dump_queue(void)
93 struct hotplug_msg *p;
96 dbg("next expected sequence is %d", expect_seqnum);
98 dbg("sequence %d in queue", p->seqnum);
103 static void dump_msg(struct hotplug_msg *pmsg)
105 dbg("sequence %d, '%s', '%s', '%s'",
106 pmsg->seqnum, pmsg->action, pmsg->devpath, pmsg->subsystem);
109 static int dispatch_msg(struct hotplug_msg *pmsg)
114 extern char **environ;
117 dbg("exec '%s'", exec_program);
119 setenv("ACTION", pmsg->action, 1);
120 setenv("DEVPATH", pmsg->devpath, 1);
122 argv[0] = exec_program;
123 argv[1] = pmsg->subsystem;
129 retval = execve(argv[0], argv, environ);
131 dbg("child execve failed");
145 static void reset_timer(void)
150 static void set_timer(void)
152 signal(SIGALRM, sig_alarmhandler);
153 alarm(timeout_value);
156 static void reset_queue(void)
158 struct hotplug_msg *p;
168 static void check_queue(void)
170 struct hotplug_msg *p;
174 while(head && head->seqnum == expect_seqnum) {
187 static void add_queue(struct hotplug_msg *pmsg)
189 struct hotplug_msg *pnewmsg;
190 struct hotplug_msg *p;
191 struct hotplug_msg *p1;
195 pnewmsg = malloc(sizeof(struct hotplug_msg));
197 pnewmsg->next = NULL;
198 while(p && pmsg->seqnum > p->seqnum) {
211 static int process_queue(void)
215 struct hotplug_msg *pmsg;
216 char buf[BUFFER_SIZE];
219 key = ftok(DEFAULT_EXEC_PROGRAM, IPC_KEY_ID);
220 pmsg = (struct hotplug_msg *) buf;
221 msgid = msgget(key, IPC_CREAT);
223 dbg("open message queue error");
227 ret = msgrcv(msgid, (struct msgbuf *) buf, BUFFER_SIZE-4, HOTPLUGMSGTYPE, 0);
229 dbg("current sequence %d, expected sequence %d", pmsg->seqnum, expect_seqnum);
231 /* init expected sequence with value from first call */
232 if (expect_seqnum == 0) {
233 expect_seqnum = pmsg->seqnum;
234 dbg("init next expected sequence number to %d", expect_seqnum);
237 if (pmsg->seqnum > expect_seqnum) {
241 if (pmsg->seqnum == expect_seqnum) {
246 dbg("timeout event for unexpected sequence number %d", pmsg->seqnum);
250 if (errno == EINTR) {
252 /* timeout, skip all missing, proceed with next queued event */
253 dbg("timeout reached, skip events %d - %d", expect_seqnum, head->seqnum-1);
254 expect_seqnum = head->seqnum;
259 dbg("ipc message receive error '%s'", strerror(errno));
267 int main(int argc, char *argv[])
269 /* get program to exec on events */
271 strncpy(exec_program, argv[1], sizeof(exec_program));
273 strcpy(exec_program, DEFAULT_EXEC_PROGRAM);
275 /* set up signal handler */
276 signal(SIGINT, sig_handler);
277 signal(SIGTERM, sig_handler);
278 signal(SIGKILL, sig_handler);
279 signal(SIGHUP, sig_handler);