]>
git.ipfire.org Git - thirdparty/systemd.git/blob - udevd.c
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>
41 #define BUFFER_SIZE 1024
42 #define EVENT_TIMEOUT_SECONDS 10
43 #define DAEMON_TIMEOUT_SECONDS 30
46 static int expect_seqnum
= 0;
47 static struct hotplug_msg
*head
= NULL
;
50 static void sig_alarmhandler(int signum
)
52 dbg("caught signal %d", signum
);
55 dbg("event timeout reached");
59 dbg("unhandled signal");
63 static void dump_queue(void)
65 struct hotplug_msg
*p
;
68 dbg("next expected sequence is %d", expect_seqnum
);
70 dbg("sequence %d in queue", p
->seqnum
);
75 static void dump_msg(struct hotplug_msg
*pmsg
)
77 dbg("sequence %d, '%s', '%s', '%s'",
78 pmsg
->seqnum
, pmsg
->action
, pmsg
->devpath
, pmsg
->subsystem
);
81 static int dispatch_msg(struct hotplug_msg
*pmsg
)
85 extern char **environ
;
89 setenv("ACTION", pmsg
->action
, 1);
90 setenv("DEVPATH", pmsg
->devpath
, 1);
91 argv
[0] = DEFAULT_UDEV_EXEC
;
92 argv
[1] = pmsg
->subsystem
;
99 execve(argv
[0], argv
, environ
);
100 dbg("exec of child failed");
104 dbg("fork of child failed");
112 static void set_timer(int seconds
)
114 signal(SIGALRM
, sig_alarmhandler
);
118 static void check_queue(void)
120 struct hotplug_msg
*p
;
124 while(head
!= NULL
&& head
->seqnum
== expect_seqnum
) {
132 set_timer(EVENT_TIMEOUT_SECONDS
);
134 set_timer(DAEMON_TIMEOUT_SECONDS
);
137 static void add_queue(struct hotplug_msg
*pmsg
)
139 struct hotplug_msg
*pnewmsg
;
140 struct hotplug_msg
*p
;
141 struct hotplug_msg
*p1
;
145 pnewmsg
= malloc(sizeof(struct hotplug_msg
));
147 pnewmsg
->next
= NULL
;
148 while(p
!= NULL
&& pmsg
->seqnum
> p
->seqnum
) {
161 static int lock_file
= -1;
162 static char *lock_filename
= ".udevd_lock";
164 static int process_queue(void)
168 struct hotplug_msg
*pmsg
;
169 char buf
[BUFFER_SIZE
];
172 key
= ftok(DEFAULT_UDEVD_EXEC
, IPC_KEY_ID
);
173 pmsg
= (struct hotplug_msg
*) buf
;
174 msgid
= msgget(key
, IPC_CREAT
);
176 dbg("open message queue error");
180 ret
= msgrcv(msgid
, (struct msgbuf
*) buf
, BUFFER_SIZE
-4, HOTPLUGMSGTYPE
, 0);
182 dbg("current sequence %d, expected sequence %d", pmsg
->seqnum
, expect_seqnum
);
184 /* init expected sequence with value from first call */
185 if (expect_seqnum
== 0) {
186 expect_seqnum
= pmsg
->seqnum
;
187 dbg("init next expected sequence number to %d", expect_seqnum
);
190 if (pmsg
->seqnum
> expect_seqnum
) {
192 set_timer(EVENT_TIMEOUT_SECONDS
);
194 if (pmsg
->seqnum
== expect_seqnum
) {
199 dbg("timeout event for unexpected sequence number %d", pmsg
->seqnum
);
203 if (errno
== EINTR
) {
205 /* event timeout, skip all missing, proceed with next queued event */
206 info("timeout reached, skip events %d - %d", expect_seqnum
, head
->seqnum
-1);
207 expect_seqnum
= head
->seqnum
;
209 info("we have nothing to do, so daemon exits...");
210 if (lock_file
>= 0) {
212 unlink(lock_filename
);
218 dbg("ipc message receive error '%s'", strerror(errno
));
225 static void sig_handler(int signum
)
227 dbg("caught signal %d", signum
);
232 if (lock_file
>= 0) {
234 unlink(lock_filename
);
240 dbg("unhandled signal");
244 static int one_and_only(void)
248 lock_file
= open(lock_filename
, O_RDWR
| O_CREAT
, 0x640);
250 /* see if we can open */
254 /* see if we can lock */
255 if (lockf(lock_file
, F_TLOCK
, 0) < 0) {
257 unlink(lock_filename
);
261 snprintf(string
, sizeof(string
), "%d\n", getpid());
262 write(lock_file
, string
, strlen(string
));
267 int main(int argc
, char *argv
[])
269 /* only let one version of the daemon run at any one time */
270 if (one_and_only() != 0)
273 /* set up signal handler */
274 signal(SIGINT
, sig_handler
);
275 signal(SIGTERM
, sig_handler
);
276 signal(SIGKILL
, sig_handler
);
278 /* we exit if we have nothing to do, next event will start us again */
279 set_timer(DAEMON_TIMEOUT_SECONDS
);