]>
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.
26 #include <sys/types.h>
44 #define BUFFER_SIZE 1024
46 static int expect_seqnum
= 0;
47 static int lock_file
= -1;
48 static char *lock_filename
= ".udevd_lock";
52 static void sig_handler(int signum
)
54 dbg("caught signal %d", signum
);
57 dbg("event timeout reached");
64 unlink(lock_filename
);
69 dbg("unhandled signal");
73 static void dump_queue(void)
75 struct hotplug_msg
*msg
;
77 list_for_each_entry(msg
, &msg_list
, list
)
78 dbg("sequence %d in queue", msg
->seqnum
);
81 static void dump_msg(struct hotplug_msg
*msg
)
83 dbg("sequence %d, '%s', '%s', '%s'",
84 msg
->seqnum
, msg
->action
, msg
->devpath
, msg
->subsystem
);
87 static int dispatch_msg(struct hotplug_msg
*msg
)
93 setenv("ACTION", msg
->action
, 1);
94 setenv("DEVPATH", msg
->devpath
, 1);
100 execl(UDEV_EXEC
, "udev", msg
->subsystem
, NULL
);
101 dbg("exec of child failed");
105 dbg("fork of child failed");
113 static void set_timeout(int seconds
)
116 dbg("set timeout in %d seconds", seconds
);
119 static void check_queue(void)
121 struct hotplug_msg
*msg
;
122 struct hotplug_msg
*tmp_msg
;
126 /* dispatch events until one is missing */
127 list_for_each_entry_safe(msg
, tmp_msg
, &msg_list
, list
) {
128 if (msg
->seqnum
!= expect_seqnum
)
132 list_del_init(&msg
->list
);
136 /* recalculate timeout */
137 if (list_empty(&msg_list
) == 0) {
138 msg_age
= time(NULL
) - msg
->queue_time
;
139 if (msg_age
> EVENT_TIMEOUT_SECONDS
-1) {
140 info("event %d, age %li seconds, skip event %d-%d",
141 msg
->seqnum
, msg_age
, expect_seqnum
, msg
->seqnum
-1);
142 expect_seqnum
= msg
->seqnum
;
145 set_timeout(EVENT_TIMEOUT_SECONDS
- msg_age
);
150 set_timeout(UDEVD_TIMEOUT_SECONDS
);
153 static int queue_msg(struct hotplug_msg
*msg
)
155 struct hotplug_msg
*new_msg
;
156 struct hotplug_msg
*tmp_msg
;
158 new_msg
= malloc(sizeof(*new_msg
));
159 if (new_msg
== NULL
) {
163 memcpy(new_msg
, msg
, sizeof(*new_msg
));
165 /* store timestamp of queuing */
166 new_msg
->queue_time
= time(NULL
);
168 /* sort message by sequence number into list*/
169 list_for_each_entry(tmp_msg
, &msg_list
, list
)
170 if (tmp_msg
->seqnum
> new_msg
->seqnum
)
172 list_add_tail(&new_msg
->list
, &tmp_msg
->list
);
177 static void work(void)
179 struct hotplug_msg
*msg
;
182 char buf
[BUFFER_SIZE
];
185 key
= ftok(UDEVD_EXEC
, IPC_KEY_ID
);
186 msg
= (struct hotplug_msg
*) buf
;
187 msgid
= msgget(key
, IPC_CREAT
);
189 dbg("open message queue error");
193 ret
= msgrcv(msgid
, (struct msgbuf
*) buf
, BUFFER_SIZE
-4, HOTPLUGMSGTYPE
, 0);
195 /* init the expected sequence with value from first call */
196 if (expect_seqnum
== 0) {
197 expect_seqnum
= msg
->seqnum
;
198 dbg("init next expected sequence number to %d", expect_seqnum
);
200 dbg("current sequence %d, expected sequence %d", msg
->seqnum
, expect_seqnum
);
201 if (msg
->seqnum
== expect_seqnum
) {
202 /* execute expected event */
209 if (msg
->seqnum
> expect_seqnum
) {
210 /* something missing, queue event*/
216 dbg("too late for event with sequence %d, even skipped ", msg
->seqnum
);
218 if (errno
== EINTR
) {
220 if (list_empty(&msg_list
)) {
221 info("we have nothing to do, so daemon exits...");
222 if (lock_file
>= 0) {
224 unlink(lock_filename
);
232 dbg("ipc message receive error '%s'", strerror(errno
));
237 static int one_and_only(void)
241 lock_file
= open(lock_filename
, O_RDWR
| O_CREAT
, 0x640);
243 /* see if we can open */
247 /* see if we can lock */
248 if (lockf(lock_file
, F_TLOCK
, 0) < 0) {
250 unlink(lock_filename
);
254 snprintf(string
, sizeof(string
), "%d\n", getpid());
255 write(lock_file
, string
, strlen(string
));
260 int main(int argc
, char *argv
[])
262 /* only let one version of the daemon run at any one time */
263 if (one_and_only() != 0)
266 /* set up signal handler */
267 signal(SIGINT
, sig_handler
);
268 signal(SIGTERM
, sig_handler
);
269 signal(SIGKILL
, sig_handler
);
270 signal(SIGALRM
, sig_handler
);
272 /* we exit if we have nothing to do, next event will start us again */
273 set_timeout(UDEVD_TIMEOUT_SECONDS
);