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>
39 #define BUFFER_SIZE 1024
40 #define TIMEOUT_SECONDS 10
42 static void reset_timer(void);
43 static void reset_queue(void);
46 static int expect_seqnum = 0;
47 static int timeout_value = TIMEOUT_SECONDS;
48 static int timeout = 0;
49 static struct hotplug_msg *head = NULL;
50 static char exec_program[100];
52 static void sig_handler(int signum)
54 dbg("caught signal %d", signum);
57 dbg("reset requested, all waiting events killed");
71 dbg("unhandled signal");
75 static void sig_alarmhandler(int signum)
77 dbg("caught signal %d", signum);
81 dbg("event timeout reached");
85 dbg("unhandled signal");
89 static void dump_queue(void)
91 struct hotplug_msg *p;
94 dbg("next expected sequence is %d", expect_seqnum);
96 dbg("sequence %d in queue", p->seqnum);
101 static void dump_msg(struct hotplug_msg *pmsg)
103 dbg("sequence %d, '%s', '%s', '%s'",
104 pmsg->seqnum, pmsg->action, pmsg->devpath, pmsg->subsystem);
107 static void dispatch_msg(struct hotplug_msg *pmsg)
110 dbg("exec '%s'", exec_program);
111 setenv("ACTION", pmsg->action, 1);
112 setenv("DEVPATH", pmsg->devpath, 1);
113 execl(exec_program, pmsg->subsystem);
116 static void reset_timer(void)
121 static void set_timer(void)
123 signal(SIGALRM, sig_alarmhandler);
124 alarm(timeout_value);
127 static void reset_queue(void)
129 struct hotplug_msg *p;
139 static void check_queue(void)
141 struct hotplug_msg *p;
145 while(head && head->seqnum == expect_seqnum) {
158 static void add_queue(struct hotplug_msg *pmsg)
160 struct hotplug_msg *pnewmsg;
161 struct hotplug_msg *p;
162 struct hotplug_msg *p1;
166 pnewmsg = malloc(sizeof(struct hotplug_msg));
168 pnewmsg->next = NULL;
169 while(p && pmsg->seqnum > p->seqnum) {
182 static int process_queue(void)
186 struct hotplug_msg *pmsg;
187 char buf[BUFFER_SIZE];
190 key = ftok(DEFAULT_EXEC_PROGRAM, IPC_KEY_ID);
191 pmsg = (struct hotplug_msg *) buf;
192 msgid = msgget(key, IPC_CREAT);
194 dbg("open message queue error");
198 ret = msgrcv(msgid, (struct msgbuf *) buf, BUFFER_SIZE-4, HOTPLUGMSGTYPE, 0);
200 dbg("current sequence %d, expected sequence %d", pmsg->seqnum, expect_seqnum);
202 /* init expected sequence with value from first call */
203 if (expect_seqnum == 0) {
204 expect_seqnum = pmsg->seqnum;
205 dbg("init next expected sequence number to %d", expect_seqnum);
208 if (pmsg->seqnum > expect_seqnum) {
212 if (pmsg->seqnum == expect_seqnum) {
217 dbg("timeout event for unexpected sequence number %d", pmsg->seqnum);
221 if (errno == EINTR) {
223 /* timeout, skip all missing, proceed with next queued event */
224 dbg("timeout reached, skip events %d - %d", expect_seqnum, head->seqnum-1);
225 expect_seqnum = head->seqnum;
230 dbg("ipc message receive error '%s'", strerror(errno));
238 int main(int argc, char *argv[])
240 /* get program to exec on events */
242 strncpy(exec_program, argv[1], sizeof(exec_program));
244 strcpy(exec_program, DEFAULT_EXEC_PROGRAM);
246 /* set up signal handler */
247 signal(SIGINT, sig_handler);
248 signal(SIGTERM, sig_handler);
249 signal(SIGKILL, sig_handler);
250 signal(SIGHUP, sig_handler);