]> git.ipfire.org Git - thirdparty/systemd.git/blame - udevd.c
add strerror() to error logs
[thirdparty/systemd.git] / udevd.c
CommitLineData
7fafc032 1/*
34c00c91 2 * udevd.c - event listener and serializer
7fafc032 3 *
6c18b1fb 4 * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org>
2f6cbd19 5 * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
7fafc032
KS
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22
a695feae 23#include <stddef.h>
7fafc032
KS
24#include <signal.h>
25#include <unistd.h>
26#include <errno.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
085cce37
KS
30#include <ctype.h>
31#include <dirent.h>
32#include <fcntl.h>
40caaeec 33#include <syslog.h>
0b3dfb3d 34#include <time.h>
138068d6
KS
35#include <sys/select.h>
36#include <sys/wait.h>
53921bfa
KS
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <sys/un.h>
dc117daa 40#include <sys/stat.h>
c895fd00 41#include <sys/ioctl.h>
88f4b648 42#include <linux/netlink.h>
7fafc032 43
a695feae 44#include "list.h"
63f61c5c 45#include "udev_libc_wrapper.h"
7fafc032 46#include "udev.h"
35b7d88c 47#include "udev_version.h"
c895fd00 48#include "udev_rules.h"
9af5bb2f 49#include "udev_utils.h"
7fafc032
KS
50#include "udevd.h"
51#include "logging.h"
52
c895fd00 53struct udev_rules rules;
3b47c739 54static int udevd_sock;
8ab44e3f 55static int uevent_netlink_sock;
c895fd00 56static int inotify_fd;
085cce37 57static pid_t sid;
13f24d59 58
f1ff8d7b 59static int signal_pipe[2] = {-1, -1};
5cab7caa 60static volatile int sigchilds_waiting;
63cc8f04 61static volatile int udev_exit;
c895fd00 62static volatile int reload_config;
f27125f9 63static int run_exec_q;
3b47c739 64static int stop_exec_q;
a15f42c4
KS
65static int max_childs;
66static int max_childs_running;
916c5e47 67static char udev_log[32];
40caaeec 68
40caaeec
KS
69static LIST_HEAD(exec_list);
70static LIST_HEAD(running_list);
a15f42c4 71
7fafc032 72
6c18b1fb 73#ifdef USE_LOG
c895fd00 74void log_message(int priority, const char *format, ...)
51a8bb2f 75{
6b493a20
KS
76 va_list args;
77
78 if (priority > udev_log_priority)
79 return;
d026a35d
GKH
80
81 va_start(args, format);
6b493a20 82 vsyslog(priority, format, args);
d026a35d 83 va_end(args);
51a8bb2f 84}
d026a35d 85#endif
51a8bb2f 86
c895fd00
KS
87static void asmlinkage udev_event_sig_handler(int signum)
88{
89 if (signum == SIGALRM)
90 exit(1);
91}
92
93static int udev_event_process(struct uevent_msg *msg)
94{
95 struct sigaction act;
96 struct udevice udev;
97 struct name_entry *name_loop;
98 int i;
99 int retval;
100
101 /* set signal handlers */
102 memset(&act, 0x00, sizeof(act));
103 act.sa_handler = (void (*)(int)) udev_event_sig_handler;
104 sigemptyset (&act.sa_mask);
105 act.sa_flags = 0;
106 sigaction(SIGALRM, &act, NULL);
107
108 /* trigger timeout to prevent hanging processes */
109 alarm(UDEV_ALARM_TIMEOUT);
110
111 /* reconstruct env from message */
112 for (i = 0; msg->envp[i]; i++)
113 putenv(msg->envp[i]);
114
115 udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
116 retval = udev_process_event(&rules, &udev);
117
118 /* run programs collected by RUN-key*/
119 if (!retval) {
120 list_for_each_entry(name_loop, &udev.run_list, node) {
121 if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
122 pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action);
123 else
124 run_program(name_loop->name, udev.subsystem, NULL, 0, NULL, (udev_log_priority >= LOG_INFO));
125 }
126 }
127
128 udev_cleanup_device(&udev);
129
130 return 0;
131}
132
fc465079
KS
133static void msg_queue_delete(struct uevent_msg *msg)
134{
135 list_del(&msg->node);
136 free(msg);
137}
138
40caaeec 139static void udev_event_run(struct uevent_msg *msg)
7fafc032 140{
90c210eb 141 pid_t pid;
90c210eb
KS
142
143 pid = fork();
144 switch (pid) {
145 case 0:
33db4b8d 146 /* child */
833b3c68
KS
147 close(uevent_netlink_sock);
148 close(udevd_sock);
c895fd00
KS
149 if (inotify_fd > 0)
150 close(inotify_fd);
c895fd00
KS
151 close(signal_pipe[READ_END]);
152 close(signal_pipe[WRITE_END]);
f602ccf0 153 logging_close();
c895fd00
KS
154
155 logging_init("udevd-event");
085cce37 156 setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
c895fd00
KS
157 udev_event_process(msg);
158 info("seq %llu finished", msg->seqnum);
159
160 logging_close();
161 exit(0);
90c210eb 162 case -1:
ff3e4bed 163 err("fork of child failed: %s", strerror(errno));
ebfc1acd 164 msg_queue_delete(msg);
2f6cbd19 165 break;
90c210eb 166 default:
2f6cbd19 167 /* get SIGCHLD in main loop */
40caaeec 168 info("seq %llu forked, pid [%d], '%s' '%s', %ld seconds old",
0b3dfb3d 169 msg->seqnum, pid, msg->action, msg->subsystem, time(NULL) - msg->queue_time);
2f6cbd19 170 msg->pid = pid;
90c210eb 171 }
7fafc032
KS
172}
173
fc465079
KS
174static void msg_queue_insert(struct uevent_msg *msg)
175{
176 msg->queue_time = time(NULL);
177
178 /* run all events with a timeout set immediately */
179 if (msg->timeout != 0) {
180 list_add_tail(&msg->node, &running_list);
181 udev_event_run(msg);
182 return;
183 }
184
185 list_add_tail(&msg->node, &exec_list);
186 run_exec_q = 1;
187}
188
189/* runs event and removes event from run queue when finished */
085cce37
KS
190static int running_processes(void)
191{
192 int f;
193 static char buf[4096];
194 int len;
195 int running;
196 const char *pos;
197
198 f = open("/proc/stat", O_RDONLY);
199 if (f == -1)
200 return -1;
201
b4f192f0 202 len = read(f, buf, sizeof(buf)-1);
085cce37
KS
203 close(f);
204
205 if (len <= 0)
206 return -1;
207 else
208 buf[len] = '\0';
209
210 pos = strstr(buf, "procs_running ");
211 if (pos == NULL)
212 return -1;
213
214 if (sscanf(pos, "procs_running %u", &running) != 1)
215 return -1;
216
217 return running;
218}
219
220/* return the number of process es in our session, count only until limit */
221static int running_processes_in_session(pid_t session, int limit)
222{
223 DIR *dir;
224 struct dirent *dent;
225 int running = 0;
226
227 dir = opendir("/proc");
228 if (!dir)
229 return -1;
230
231 /* read process info from /proc */
232 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
233 int f;
234 char procdir[64];
235 char line[256];
236 const char *pos;
237 char state;
238 pid_t ppid, pgrp, sess;
239 int len;
240
241 if (!isdigit(dent->d_name[0]))
242 continue;
243
244 snprintf(procdir, sizeof(procdir), "/proc/%s/stat", dent->d_name);
245 procdir[sizeof(procdir)-1] = '\0';
246
247 f = open(procdir, O_RDONLY);
248 if (f == -1)
249 continue;
250
b4f192f0 251 len = read(f, line, sizeof(line)-1);
085cce37
KS
252 close(f);
253
254 if (len <= 0)
255 continue;
256 else
257 line[len] = '\0';
258
259 /* skip ugly program name */
260 pos = strrchr(line, ')') + 2;
261 if (pos == NULL)
262 continue;
263
264 if (sscanf(pos, "%c %d %d %d ", &state, &ppid, &pgrp, &sess) != 4)
265 continue;
266
267 /* count only processes in our session */
268 if (sess != session)
269 continue;
270
271 /* count only running, no sleeping processes */
272 if (state != 'R')
273 continue;
274
275 running++;
276 if (limit > 0 && running >= limit)
277 break;
278 }
279 closedir(dir);
280
281 return running;
282}
283
7b6571a9
KS
284static int compare_devpath(const char *running, const char *waiting)
285{
286 int i;
287
63f61c5c 288 for (i = 0; i < PATH_SIZE; i++) {
7b6571a9
KS
289 /* identical device event found */
290 if (running[i] == '\0' && waiting[i] == '\0')
291 return 1;
292
293 /* parent device event found */
294 if (running[i] == '\0' && waiting[i] == '/')
295 return 2;
296
297 /* child device event found */
298 if (running[i] == '/' && waiting[i] == '\0')
299 return 3;
300
301 /* no matching event */
302 if (running[i] != waiting[i])
303 break;
304 }
305
306 return 0;
307}
308
309/* returns still running task for the same device, its parent or its physical device */
a15f42c4 310static int running_with_devpath(struct uevent_msg *msg, int limit)
7fafc032 311{
3b47c739 312 struct uevent_msg *loop_msg;
a15f42c4 313 int childs_count = 0;
7b6571a9
KS
314
315 if (msg->devpath == NULL)
a15f42c4 316 return 0;
79721e0a 317
f8a178a3 318 list_for_each_entry(loop_msg, &running_list, node) {
a15f42c4
KS
319 if (limit && childs_count++ > limit) {
320 dbg("%llu, maximum number (%i) of child reached", msg->seqnum, childs_count);
321 return 1;
322 }
7b6571a9 323 if (loop_msg->devpath == NULL)
80513ea3
KS
324 continue;
325
7b6571a9 326 /* return running parent/child device event */
a15f42c4
KS
327 if (compare_devpath(loop_msg->devpath, msg->devpath) != 0) {
328 dbg("%llu, child device event still running %llu (%s)",
329 msg->seqnum, loop_msg->seqnum, loop_msg->devpath);
330 return 2;
331 }
79721e0a 332
7b6571a9 333 /* return running physical device event */
79721e0a 334 if (msg->physdevpath && msg->action && strcmp(msg->action, "add") == 0)
a15f42c4
KS
335 if (compare_devpath(loop_msg->devpath, msg->physdevpath) != 0) {
336 dbg("%llu, physical device event still running %llu (%s)",
337 msg->seqnum, loop_msg->seqnum, loop_msg->devpath);
338 return 3;
339 }
80513ea3
KS
340 }
341
a15f42c4 342 return 0;
7fafc032
KS
343}
344
79721e0a 345/* exec queue management routine executes the events and serializes events in the same sequence */
fc465079 346static void msg_queue_manager(void)
7fafc032 347{
3b47c739
KS
348 struct uevent_msg *loop_msg;
349 struct uevent_msg *tmp_msg;
085cce37
KS
350 int running;
351
8ab44e3f
KS
352 if (list_empty(&exec_list))
353 return;
354
085cce37
KS
355 running = running_processes();
356 dbg("%d processes runnning on system", running);
357 if (running < 0)
a15f42c4 358 running = max_childs_running;
53921bfa 359
f8a178a3 360 list_for_each_entry_safe(loop_msg, tmp_msg, &exec_list, node) {
085cce37 361 /* check running processes in our session and possibly throttle */
a15f42c4
KS
362 if (running >= max_childs_running) {
363 running = running_processes_in_session(sid, max_childs_running+10);
364 dbg("at least %d processes running in session", running);
365 if (running >= max_childs_running) {
fc465079 366 dbg("delay seq %llu, too many processes already running", loop_msg->seqnum);
085cce37
KS
367 return;
368 }
369 }
370
fc465079
KS
371 /* don't run two processes for the same devpath and wait for the parent*/
372 if (running_with_devpath(loop_msg, max_childs)) {
a15f42c4 373 dbg("delay seq %llu (%s)", loop_msg->seqnum, loop_msg->devpath);
fc465079
KS
374 continue;
375 }
376
377 /* move event to run list */
378 list_move_tail(&loop_msg->node, &running_list);
379 udev_event_run(loop_msg);
380 running++;
381 dbg("moved seq %llu to running list", loop_msg->seqnum);
53921bfa
KS
382 }
383}
384
3b47c739 385static struct uevent_msg *get_msg_from_envbuf(const char *buf, int buf_size)
88f4b648
KS
386{
387 int bufpos;
388 int i;
3b47c739 389 struct uevent_msg *msg;
ebfc1acd
KS
390 int major = 0;
391 int minor = 0;
88f4b648 392
3b47c739 393 msg = malloc(sizeof(struct uevent_msg) + buf_size);
88f4b648
KS
394 if (msg == NULL)
395 return NULL;
3b47c739 396 memset(msg, 0x00, sizeof(struct uevent_msg) + buf_size);
88f4b648
KS
397
398 /* copy environment buffer and reconstruct envp */
399 memcpy(msg->envbuf, buf, buf_size);
400 bufpos = 0;
3b47c739 401 for (i = 0; (bufpos < buf_size) && (i < UEVENT_NUM_ENVP-2); i++) {
88f4b648
KS
402 int keylen;
403 char *key;
404
405 key = &msg->envbuf[bufpos];
406 keylen = strlen(key);
407 msg->envp[i] = key;
408 bufpos += keylen + 1;
409 dbg("add '%s' to msg.envp[%i]", msg->envp[i], i);
410
411 /* remember some keys for further processing */
412 if (strncmp(key, "ACTION=", 7) == 0)
413 msg->action = &key[7];
ebfc1acd 414 else if (strncmp(key, "DEVPATH=", 8) == 0)
88f4b648 415 msg->devpath = &key[8];
ebfc1acd 416 else if (strncmp(key, "SUBSYSTEM=", 10) == 0)
88f4b648 417 msg->subsystem = &key[10];
ebfc1acd 418 else if (strncmp(key, "SEQNUM=", 7) == 0)
88f4b648 419 msg->seqnum = strtoull(&key[7], NULL, 10);
ebfc1acd 420 else if (strncmp(key, "PHYSDEVPATH=", 12) == 0)
88f4b648 421 msg->physdevpath = &key[12];
ebfc1acd
KS
422 else if (strncmp(key, "MAJOR=", 6) == 0)
423 major = strtoull(&key[6], NULL, 10);
424 else if (strncmp(key, "MINOR=", 6) == 0)
425 minor = strtoull(&key[6], NULL, 10);
426 else if (strncmp(key, "TIMEOUT=", 8) == 0)
88f4b648
KS
427 msg->timeout = strtoull(&key[8], NULL, 10);
428 }
ebfc1acd 429 msg->devt = makedev(major, minor);
88f4b648
KS
430 msg->envp[i++] = "UDEVD_EVENT=1";
431 msg->envp[i] = NULL;
432
433 return msg;
434}
435
3b47c739
KS
436/* receive the udevd message from userspace */
437static struct uevent_msg *get_udevd_msg(void)
7fafc032 438{
3b47c739
KS
439 static struct udevd_msg usend_msg;
440 struct uevent_msg *msg;
4a231017 441 ssize_t size;
0028653c
KS
442 struct msghdr smsg;
443 struct cmsghdr *cmsg;
444 struct iovec iov;
445 struct ucred *cred;
446 char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
4a231017 447 int envbuf_size;
8ab44e3f 448 int *intval;
a695feae 449
3b47c739 450 memset(&usend_msg, 0x00, sizeof(struct udevd_msg));
4a231017 451 iov.iov_base = &usend_msg;
3b47c739 452 iov.iov_len = sizeof(struct udevd_msg);
0028653c
KS
453
454 memset(&smsg, 0x00, sizeof(struct msghdr));
455 smsg.msg_iov = &iov;
456 smsg.msg_iovlen = 1;
457 smsg.msg_control = cred_msg;
458 smsg.msg_controllen = sizeof(cred_msg);
459
3b47c739 460 size = recvmsg(udevd_sock, &smsg, 0);
4a231017 461 if (size < 0) {
2f6cbd19 462 if (errno != EINTR)
ff3e4bed 463 err("unable to receive udevd message: %s", strerror(errno));
021a294c 464 return NULL;
53921bfa 465 }
0028653c
KS
466 cmsg = CMSG_FIRSTHDR(&smsg);
467 cred = (struct ucred *) CMSG_DATA(cmsg);
468
7b1cbec9 469 if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
199cdd86 470 err("no sender credentials received, message ignored");
021a294c 471 return NULL;
7b1cbec9
KS
472 }
473
0028653c 474 if (cred->uid != 0) {
199cdd86 475 err("sender uid=%i, message ignored", cred->uid);
021a294c 476 return NULL;
4a231017
KS
477 }
478
479 if (strncmp(usend_msg.magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
199cdd86 480 err("message magic '%s' doesn't match, ignore it", usend_msg.magic);
021a294c 481 return NULL;
0028653c
KS
482 }
483
8ab44e3f
KS
484 switch (usend_msg.type) {
485 case UDEVD_UEVENT_UDEVSEND:
486 case UDEVD_UEVENT_INITSEND:
199cdd86 487 info("udevd event message received");
3b47c739
KS
488 envbuf_size = size - offsetof(struct udevd_msg, envbuf);
489 dbg("envbuf_size=%i", envbuf_size);
490 msg = get_msg_from_envbuf(usend_msg.envbuf, envbuf_size);
491 if (msg == NULL)
492 return NULL;
510de9c9 493 msg->type = usend_msg.type;
3b47c739
KS
494 return msg;
495 case UDEVD_STOP_EXEC_QUEUE:
8ab44e3f 496 info("udevd message (STOP_EXEC_QUEUE) received");
3b47c739
KS
497 stop_exec_q = 1;
498 break;
499 case UDEVD_START_EXEC_QUEUE:
8ab44e3f 500 info("udevd message (START_EXEC_QUEUE) received");
3b47c739 501 stop_exec_q = 0;
fc465079 502 msg_queue_manager();
3b47c739 503 break;
8ab44e3f
KS
504 case UDEVD_SET_LOG_LEVEL:
505 intval = (int *) usend_msg.envbuf;
506 info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i", *intval);
507 udev_log_priority = *intval;
916c5e47
KS
508 sprintf(udev_log, "UDEV_LOG=%i", udev_log_priority);
509 putenv(udev_log);
8ab44e3f
KS
510 break;
511 case UDEVD_SET_MAX_CHILDS:
512 intval = (int *) usend_msg.envbuf;
513 info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
514 max_childs = *intval;
515 break;
c895fd00
KS
516 case UDEVD_RELOAD_RULES:
517 info("udevd message (RELOAD_RULES) received");
518 reload_config = 1;
519 break;
3b47c739
KS
520 default:
521 dbg("unknown message type");
522 }
523 return NULL;
88f4b648 524}
4a231017 525
88f4b648 526/* receive the kernel user event message and do some sanity checks */
8ab44e3f 527static struct uevent_msg *get_netlink_msg(void)
88f4b648 528{
3b47c739 529 struct uevent_msg *msg;
88f4b648
KS
530 int bufpos;
531 ssize_t size;
3b47c739 532 static char buffer[UEVENT_BUFFER_SIZE + 512];
88f4b648 533 char *pos;
4a231017 534
8ab44e3f 535 size = recv(uevent_netlink_sock, &buffer, sizeof(buffer), 0);
88f4b648
KS
536 if (size < 0) {
537 if (errno != EINTR)
ff3e4bed 538 err("unable to receive udevd message: %s", strerror(errno));
88f4b648
KS
539 return NULL;
540 }
4a231017 541
88f4b648
KS
542 if ((size_t)size > sizeof(buffer)-1)
543 size = sizeof(buffer)-1;
544 buffer[size] = '\0';
ebfc1acd 545 dbg("uevent_size=%zi", size);
4a231017 546
88f4b648
KS
547 /* start of event payload */
548 bufpos = strlen(buffer)+1;
549 msg = get_msg_from_envbuf(&buffer[bufpos], size-bufpos);
550 if (msg == NULL)
551 return NULL;
8ab44e3f 552 msg->type = UDEVD_UEVENT_NETLINK;
4a231017 553
88f4b648
KS
554 /* validate message */
555 pos = strchr(buffer, '@');
556 if (pos == NULL) {
199cdd86 557 err("invalid uevent '%s'", buffer);
88f4b648
KS
558 free(msg);
559 return NULL;
560 }
561 pos[0] = '\0';
79721e0a 562
88f4b648 563 if (msg->action == NULL) {
dfedc446 564 info("no ACTION in payload found, skip event '%s'", buffer);
88f4b648
KS
565 free(msg);
566 return NULL;
567 }
7f7ae03a 568
88f4b648 569 if (strcmp(msg->action, buffer) != 0) {
199cdd86 570 err("ACTION in payload does not match uevent, skip event '%s'", buffer);
88f4b648
KS
571 free(msg);
572 return NULL;
53921bfa 573 }
a695feae 574
021a294c 575 return msg;
a695feae 576}
1c5c245e 577
e5a5b54a 578static void asmlinkage sig_handler(int signum)
7fafc032 579{
53921bfa
KS
580 switch (signum) {
581 case SIGINT:
582 case SIGTERM:
63cc8f04 583 udev_exit = 1;
53921bfa 584 break;
2f6cbd19 585 case SIGCHLD:
f27125f9 586 /* set flag, then write to pipe if needed */
5cab7caa 587 sigchilds_waiting = 1;
2f6cbd19 588 break;
c895fd00
KS
589 case SIGHUP:
590 reload_config = 1;
591 break;
f27125f9 592 }
5a73b25f 593
c6303c13
KS
594 /* write to pipe, which will wakeup select() in our mainloop */
595 write(signal_pipe[WRITE_END], "", 1);
33db4b8d 596}
7fafc032 597
2f6cbd19
KS
598static void udev_done(int pid)
599{
600 /* find msg associated with pid and delete it */
3b47c739 601 struct uevent_msg *msg;
2f6cbd19 602
f8a178a3 603 list_for_each_entry(msg, &running_list, node) {
2f6cbd19 604 if (msg->pid == pid) {
fc465079 605 info("seq %llu, pid [%d] exit, %ld seconds old", msg->seqnum, msg->pid, time(NULL) - msg->queue_time);
ebfc1acd 606 msg_queue_delete(msg);
3169e8d1 607
fc465079 608 /* there may be events waiting with the same devpath */
f27125f9 609 run_exec_q = 1;
2f6cbd19
KS
610 return;
611 }
612 }
613}
614
5cab7caa 615static void reap_sigchilds(void)
f27125f9 616{
40caaeec 617 pid_t pid;
ce043f85 618
40caaeec
KS
619 while (1) {
620 pid = waitpid(-1, NULL, WNOHANG);
621 if (pid <= 0)
f27125f9 622 break;
40caaeec 623 udev_done(pid);
f27125f9 624 }
625}
626
3b47c739 627static int init_udevd_socket(void)
33db4b8d 628{
53921bfa 629 struct sockaddr_un saddr;
a5c606f6 630 const int buffersize = 16 * 1024 * 1024;
1dadabd7 631 socklen_t addrlen;
5cab7caa 632 const int feature_on = 1;
c2cf4012
KS
633 int retval;
634
635 memset(&saddr, 0x00, sizeof(saddr));
636 saddr.sun_family = AF_LOCAL;
637 /* use abstract namespace for socket path */
638 strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
639 addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
640
3b47c739
KS
641 udevd_sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
642 if (udevd_sock == -1) {
ff3e4bed 643 err("error getting socket: %s", strerror(errno));
c2cf4012
KS
644 return -1;
645 }
646
cbbde2ba 647 /* set receive buffersize */
a5c606f6 648 setsockopt(udevd_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
cbbde2ba 649
c2cf4012 650 /* the bind takes care of ensuring only one copy running */
3b47c739 651 retval = bind(udevd_sock, (struct sockaddr *) &saddr, addrlen);
c2cf4012 652 if (retval < 0) {
ff3e4bed 653 err("bind failed: %s", strerror(errno));
c2cf4012
KS
654 return -1;
655 }
656
657 /* enable receiving of the sender credentials */
3b47c739 658 setsockopt(udevd_sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
c2cf4012
KS
659
660 return 0;
661}
662
8ab44e3f 663static int init_uevent_netlink_sock(void)
88f4b648
KS
664{
665 struct sockaddr_nl snl;
a5c606f6 666 const int buffersize = 16 * 1024 * 1024;
88f4b648
KS
667 int retval;
668
669 memset(&snl, 0x00, sizeof(struct sockaddr_nl));
670 snl.nl_family = AF_NETLINK;
671 snl.nl_pid = getpid();
672 snl.nl_groups = 0xffffffff;
673
8ab44e3f
KS
674 uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
675 if (uevent_netlink_sock == -1) {
ff3e4bed 676 err("error getting socket: %s", strerror(errno));
88f4b648
KS
677 return -1;
678 }
679
cbbde2ba 680 /* set receive buffersize */
a5c606f6 681 setsockopt(uevent_netlink_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
cbbde2ba 682
833b3c68 683 retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl));
88f4b648 684 if (retval < 0) {
ff3e4bed 685 err("bind failed: %s", strerror(errno));
8ab44e3f
KS
686 close(uevent_netlink_sock);
687 uevent_netlink_sock = -1;
88f4b648
KS
688 return -1;
689 }
88f4b648
KS
690 return 0;
691}
692
c2cf4012
KS
693int main(int argc, char *argv[], char *envp[])
694{
c2cf4012 695 int retval;
3904a758 696 int fd;
f8911dbb 697 struct sigaction act;
f27125f9 698 fd_set readfds;
a15f42c4 699 const char *value;
561d4c5a
KS
700 int daemonize = 0;
701 int i;
833b3c68 702 int rc = 0;
0b3dfb3d 703 int maxfd;
53921bfa 704
833b3c68 705 /* redirect std fd's, if the kernel forks us, we don't have them at all */
3904a758
KS
706 fd = open("/dev/null", O_RDWR);
707 if (fd >= 0) {
708 if (fd != STDIN_FILENO)
709 dup2(fd, STDIN_FILENO);
710 if (fd != STDOUT_FILENO)
711 dup2(fd, STDOUT_FILENO);
712 if (fd != STDERR_FILENO)
713 dup2(fd, STDERR_FILENO);
714 if (fd > STDERR_FILENO)
715 close(fd);
3f9f8de4
KS
716 }
717
7257cb18 718 logging_init("udevd");
3904a758 719 if (fd < 0)
ff3e4bed 720 err("fatal, could not open /dev/null: %s", strerror(errno));
3f9f8de4 721
6b493a20 722 udev_init_config();
896e5aa9 723 dbg("version %s", UDEV_VERSION);
95a6f4c8 724
7b1cbec9 725 if (getuid() != 0) {
6b493a20 726 err("need to be root, exit");
ec9cc012 727 goto exit;
7b1cbec9 728 }
5cab7caa 729
833b3c68 730 /* parse commandline options */
561d4c5a
KS
731 for (i = 1 ; i < argc; i++) {
732 char *arg = argv[i];
733 if (strcmp(arg, "--daemon") == 0 || strcmp(arg, "-d") == 0) {
734 info("will daemonize");
735 daemonize = 1;
736 }
737 if (strcmp(arg, "--stop-exec-queue") == 0) {
8ab44e3f 738 info("will not execute events until START_EXEC_QUEUE is received");
561d4c5a
KS
739 stop_exec_q = 1;
740 }
741 }
40caaeec 742
833b3c68
KS
743 /* init sockets to receive events */
744 if (init_udevd_socket() < 0) {
745 if (errno == EADDRINUSE) {
746 dbg("another udevd running, exit");
747 rc = 1;
748 } else {
749 dbg("error initializing udevd socket: %s", strerror(errno));
750 rc = 2;
751 }
752 goto exit;
753 }
754
755 if (init_uevent_netlink_sock() < 0) {
756 err("uevent socket not available");
757 rc = 3;
758 goto exit;
759 }
760
761 /* parse the rules and keep it in memory */
287814b2 762 udev_rules_init(&rules, 1);
833b3c68 763
561d4c5a 764 if (daemonize) {
f15515b5
KS
765 pid_t pid;
766
767 pid = fork();
768 switch (pid) {
769 case 0:
833b3c68 770 dbg("daemonized fork running");
f15515b5
KS
771 break;
772 case -1:
ff3e4bed 773 err("fork of daemon failed: %s", strerror(errno));
833b3c68 774 rc = 4;
f15515b5
KS
775 goto exit;
776 default:
833b3c68
KS
777 dbg("child [%u] running, parent exits", pid);
778 goto exit;
f15515b5
KS
779 }
780 }
781
3904a758 782 /* set scheduling priority for the daemon */
085cce37
KS
783 setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
784
3904a758 785 chdir("/");
74adec7d 786 umask(022);
3904a758
KS
787
788 /* become session leader */
789 sid = setsid();
790 dbg("our session is %d", sid);
791
792 /* OOM_DISABLE == -17 */
793 fd = open("/proc/self/oom_adj", O_RDWR);
794 if (fd < 0)
ff3e4bed 795 err("error disabling OOM: %s", strerror(errno));
3904a758
KS
796 else {
797 write(fd, "-17", 3);
798 close(fd);
799 }
800
f27125f9 801 /* setup signal handler pipe */
f1ff8d7b 802 retval = pipe(signal_pipe);
e5a2989e 803 if (retval < 0) {
6b493a20 804 err("error getting pipes: %s", strerror(errno));
ec9cc012 805 goto exit;
e5a2989e 806 }
f1ff8d7b 807 retval = fcntl(signal_pipe[READ_END], F_SETFL, O_NONBLOCK);
c8fa2d8b 808 if (retval < 0) {
6b493a20 809 err("error fcntl on read pipe: %s", strerror(errno));
ec9cc012 810 goto exit;
c8fa2d8b 811 }
f1ff8d7b 812 retval = fcntl(signal_pipe[WRITE_END], F_SETFL, O_NONBLOCK);
e5a2989e 813 if (retval < 0) {
6b493a20 814 err("error fcntl on write pipe: %s", strerror(errno));
ec9cc012 815 goto exit;
e5a2989e 816 }
f27125f9 817
818 /* set signal handlers */
0786e8e5 819 memset(&act, 0x00, sizeof(struct sigaction));
6b493a20 820 act.sa_handler = (void (*)(int)) sig_handler;
f27125f9 821 sigemptyset(&act.sa_mask);
f8911dbb
KS
822 act.sa_flags = SA_RESTART;
823 sigaction(SIGINT, &act, NULL);
824 sigaction(SIGTERM, &act, NULL);
f8911dbb 825 sigaction(SIGCHLD, &act, NULL);
63cc8f04 826 sigaction(SIGHUP, &act, NULL);
7fafc032 827
c895fd00
KS
828 /* watch rules directory */
829 inotify_fd = inotify_init();
830 if (inotify_fd > 0)
831 inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
0028653c 832
a15f42c4
KS
833 /* maximum limit of forked childs */
834 value = getenv("UDEVD_MAX_CHILDS");
835 if (value)
836 max_childs = strtoul(value, NULL, 10);
837 else
838 max_childs = UDEVD_MAX_CHILDS;
839 info("initialize max_childs to %u", max_childs);
840
841 /* start to throttle forking if maximum number of _running_ childs is reached */
842 value = getenv("UDEVD_MAX_CHILDS_RUNNING");
843 if (value)
844 max_childs_running = strtoull(value, NULL, 10);
845 else
846 max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
847 info("initialize max_childs_running to %u", max_childs_running);
8b726878 848
c895fd00
KS
849 /* clear environment for forked event processes */
850 clearenv();
851
40caaeec 852 /* export log_priority , as called programs may want to follow that setting */
916c5e47
KS
853 sprintf(udev_log, "UDEV_LOG=%i", udev_log_priority);
854 putenv(udev_log);
40caaeec 855
0b3dfb3d
KS
856 maxfd = udevd_sock;
857 maxfd = UDEV_MAX(maxfd, uevent_netlink_sock);
858 maxfd = UDEV_MAX(maxfd, signal_pipe[READ_END]);
859 maxfd = UDEV_MAX(maxfd, inotify_fd);
860
63cc8f04 861 while (!udev_exit) {
3b47c739 862 struct uevent_msg *msg;
40caaeec 863 int fdcount;
021a294c 864
40caaeec 865 FD_ZERO(&readfds);
f1ff8d7b 866 FD_SET(signal_pipe[READ_END], &readfds);
40caaeec 867 FD_SET(udevd_sock, &readfds);
833b3c68 868 FD_SET(uevent_netlink_sock, &readfds);
c895fd00
KS
869 if (inotify_fd > 0)
870 FD_SET(inotify_fd, &readfds);
e5a2989e 871
0b3dfb3d 872 fdcount = select(maxfd+1, &readfds, NULL, NULL, NULL);
40caaeec 873 if (fdcount < 0) {
e5a2989e
KS
874 if (errno != EINTR)
875 dbg("error in select: %s", strerror(errno));
f27125f9 876 continue;
2f6cbd19 877 }
e5a2989e 878
63cc8f04 879 /* get user socket message */
40caaeec 880 if (FD_ISSET(udevd_sock, &readfds)) {
3b47c739 881 msg = get_udevd_msg();
88f4b648 882 if (msg) {
0b3dfb3d
KS
883 if (msg->type == UDEVD_UEVENT_UDEVSEND && msg->seqnum != 0) {
884 info("skip non-kernel message with SEQNUM");
88f4b648 885 free(msg);
d2ecd6a1
KS
886 } else
887 msg_queue_insert(msg);
88f4b648
KS
888 }
889 }
890
63cc8f04 891 /* get kernel netlink message */
833b3c68 892 if (FD_ISSET(uevent_netlink_sock, &readfds)) {
8ab44e3f 893 msg = get_netlink_msg();
0b3dfb3d 894 if (msg)
021a294c
KS
895 msg_queue_insert(msg);
896 }
e5a2989e 897
63cc8f04 898 /* received a signal, clear our notification pipe */
c6303c13
KS
899 if (FD_ISSET(signal_pipe[READ_END], &readfds)) {
900 char buf[256];
901
902 read(signal_pipe[READ_END], &buf, sizeof(buf));
40caaeec 903 }
e5a2989e 904
c895fd00
KS
905 /* rules directory inotify watch */
906 if ((inotify_fd > 0) && FD_ISSET(inotify_fd, &readfds)) {
907 int nbytes;
908
909 /* discard all possible events, we can just reload the config */
910 if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) {
911 char *buf;
912
913 reload_config = 1;
914 buf = malloc(nbytes);
915 if (!buf) {
916 err("error getting buffer for inotify, disable watching");
917 close(inotify_fd);
918 inotify_fd = -1;
919 }
920 read(inotify_fd, buf, nbytes);
921 free(buf);
922 }
923 }
924
925 /* rules changed, set by inotify or a signal*/
926 if (reload_config) {
927 reload_config = 0;
928 udev_rules_close(&rules);
287814b2 929 udev_rules_init(&rules, 1);
c895fd00
KS
930 }
931
0b3dfb3d 932 /* forked child has returned */
5cab7caa
KS
933 if (sigchilds_waiting) {
934 sigchilds_waiting = 0;
935 reap_sigchilds();
f27125f9 936 }
e5a2989e 937
f27125f9 938 if (run_exec_q) {
f27125f9 939 run_exec_q = 0;
3b47c739 940 if (!stop_exec_q)
fc465079 941 msg_queue_manager();
53921bfa 942 }
53921bfa 943 }
ec9cc012 944
53921bfa 945exit:
c895fd00
KS
946 udev_rules_close(&rules);
947
f1ff8d7b
KS
948 if (signal_pipe[READ_END] > 0)
949 close(signal_pipe[READ_END]);
950 if (signal_pipe[WRITE_END] > 0)
951 close(signal_pipe[WRITE_END]);
2b996ad1 952
63cc8f04
KS
953 if (udevd_sock > 0)
954 close(udevd_sock);
c895fd00
KS
955 if (inotify_fd > 0)
956 close(inotify_fd);
63cc8f04
KS
957 if (uevent_netlink_sock > 0)
958 close(uevent_netlink_sock);
959
7257cb18 960 logging_close();
63cc8f04 961
833b3c68 962 return rc;
7fafc032 963}