12e7bf158SAlex Hornung /*
22e7bf158SAlex Hornung * Copyright (c) 2010 The DragonFly Project. All rights reserved.
32e7bf158SAlex Hornung *
42e7bf158SAlex Hornung * This code is derived from software contributed to The DragonFly Project
52e7bf158SAlex Hornung * by Alex Hornung <ahornung@gmail.com>
62e7bf158SAlex Hornung *
72e7bf158SAlex Hornung * Redistribution and use in source and binary forms, with or without
82e7bf158SAlex Hornung * modification, are permitted provided that the following conditions
92e7bf158SAlex Hornung * are met:
102e7bf158SAlex Hornung *
112e7bf158SAlex Hornung * 1. Redistributions of source code must retain the above copyright
122e7bf158SAlex Hornung * notice, this list of conditions and the following disclaimer.
132e7bf158SAlex Hornung * 2. Redistributions in binary form must reproduce the above copyright
142e7bf158SAlex Hornung * notice, this list of conditions and the following disclaimer in
152e7bf158SAlex Hornung * the documentation and/or other materials provided with the
162e7bf158SAlex Hornung * distribution.
172e7bf158SAlex Hornung * 3. Neither the name of The DragonFly Project nor the names of its
182e7bf158SAlex Hornung * contributors may be used to endorse or promote products derived
192e7bf158SAlex Hornung * from this software without specific, prior written permission.
202e7bf158SAlex Hornung *
212e7bf158SAlex Hornung * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
222e7bf158SAlex Hornung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
232e7bf158SAlex Hornung * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
242e7bf158SAlex Hornung * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
252e7bf158SAlex Hornung * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
262e7bf158SAlex Hornung * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
272e7bf158SAlex Hornung * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
282e7bf158SAlex Hornung * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
292e7bf158SAlex Hornung * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
302e7bf158SAlex Hornung * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
312e7bf158SAlex Hornung * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
322e7bf158SAlex Hornung * SUCH DAMAGE.
332e7bf158SAlex Hornung */
342e7bf158SAlex Hornung #include <sys/types.h>
352e7bf158SAlex Hornung #include <sys/device.h>
362e7bf158SAlex Hornung #include <sys/wait.h>
372e7bf158SAlex Hornung #include <sys/socket.h>
382e7bf158SAlex Hornung #include <sys/ioctl.h>
392e7bf158SAlex Hornung #include <sys/poll.h>
402e7bf158SAlex Hornung #include <sys/queue.h>
412e7bf158SAlex Hornung #include <sys/un.h>
422e7bf158SAlex Hornung
432e7bf158SAlex Hornung #include <err.h>
442e7bf158SAlex Hornung #include <errno.h>
452e7bf158SAlex Hornung #include <fcntl.h>
462e7bf158SAlex Hornung #include <libgen.h>
472e7bf158SAlex Hornung #include <regex.h>
482e7bf158SAlex Hornung #include <signal.h>
492e7bf158SAlex Hornung #include <stdarg.h>
502e7bf158SAlex Hornung #include <stdio.h>
512e7bf158SAlex Hornung #include <stdlib.h>
522e7bf158SAlex Hornung #include <string.h>
532e7bf158SAlex Hornung #include <syslog.h>
542e7bf158SAlex Hornung #include <unistd.h>
552e7bf158SAlex Hornung #include <pthread.h>
562e7bf158SAlex Hornung
572e7bf158SAlex Hornung #include <libprop/proplib.h>
582e7bf158SAlex Hornung #include <sys/udev.h>
592e7bf158SAlex Hornung #include "udevd.h"
602e7bf158SAlex Hornung
61ac859449SAntonio Huete Jimenez int debugopt = 0;
62ac859449SAntonio Huete Jimenez
632e7bf158SAlex Hornung static int udevfd;
643913f938SAlex Hornung static int hangup_ongoing = 0;
653913f938SAlex Hornung static struct pollfd fds[NFDS];
662e7bf158SAlex Hornung
672e7bf158SAlex Hornung extern pthread_mutex_t monitor_lock;
682e7bf158SAlex Hornung extern TAILQ_HEAD(udev_monitor_list_head, udev_monitor) udev_monitor_list;
692e7bf158SAlex Hornung extern TAILQ_HEAD(pdev_array_list_head, pdev_array_entry) pdev_array_list;
702e7bf158SAlex Hornung
71ac859449SAntonio Huete Jimenez static void usage(void);
72ac859449SAntonio Huete Jimenez
732e7bf158SAlex Hornung int match_dev_dict(prop_dictionary_t, prop_dictionary_t);
742e7bf158SAlex Hornung prop_dictionary_t find_dev_dict(int64_t, prop_dictionary_t, int *);
752e7bf158SAlex Hornung
762e7bf158SAlex Hornung void udev_read_event(int);
772e7bf158SAlex Hornung prop_array_t udev_getdevs(int);
782e7bf158SAlex Hornung
79ac859449SAntonio Huete Jimenez static
80ac859449SAntonio Huete Jimenez void
usage(void)81ac859449SAntonio Huete Jimenez usage(void)
82ac859449SAntonio Huete Jimenez {
83ac859449SAntonio Huete Jimenez fprintf(stderr, "usage: udevd [-d]\n");
84ac859449SAntonio Huete Jimenez exit(1);
85ac859449SAntonio Huete Jimenez }
86ac859449SAntonio Huete Jimenez
872e7bf158SAlex Hornung int
match_dev_dict(prop_dictionary_t dict,prop_dictionary_t match_dict)882e7bf158SAlex Hornung match_dev_dict(prop_dictionary_t dict, prop_dictionary_t match_dict)
892e7bf158SAlex Hornung {
902e7bf158SAlex Hornung prop_number_t pn, pn2;
912e7bf158SAlex Hornung prop_string_t ps, ps2;
922e7bf158SAlex Hornung
932e7bf158SAlex Hornung if (dict == NULL)
942e7bf158SAlex Hornung return 0;
952e7bf158SAlex Hornung
962e7bf158SAlex Hornung if ((ps = prop_dictionary_get(dict, "name")) == NULL)
972e7bf158SAlex Hornung return 0;
982e7bf158SAlex Hornung if ((ps2 = prop_dictionary_get(match_dict, "name")) == NULL)
992e7bf158SAlex Hornung return 0;
1002e7bf158SAlex Hornung if (!prop_string_equals(ps, ps2))
1012e7bf158SAlex Hornung return 0;
1022e7bf158SAlex Hornung
1032e7bf158SAlex Hornung if ((pn = prop_dictionary_get(dict, "devnum")) == NULL)
1042e7bf158SAlex Hornung return 0;
1052e7bf158SAlex Hornung if ((pn2 = prop_dictionary_get(match_dict, "devnum")) == NULL)
1062e7bf158SAlex Hornung return 0;
1072e7bf158SAlex Hornung if (!prop_number_equals(pn, pn2))
1082e7bf158SAlex Hornung return 0;
1092e7bf158SAlex Hornung
1102e7bf158SAlex Hornung if ((pn = prop_dictionary_get(dict, "kptr")) == NULL)
1112e7bf158SAlex Hornung return 0;
1122e7bf158SAlex Hornung if ((pn2 = prop_dictionary_get(match_dict, "kptr")) == NULL)
1132e7bf158SAlex Hornung return 0;
1142e7bf158SAlex Hornung if (!prop_number_equals(pn, pn2))
1152e7bf158SAlex Hornung return 0;
1162e7bf158SAlex Hornung
1172e7bf158SAlex Hornung return 1;
1182e7bf158SAlex Hornung }
1192e7bf158SAlex Hornung
1202e7bf158SAlex Hornung prop_dictionary_t
find_dev_dict(int64_t generation,prop_dictionary_t match_dict,int * idx)1212e7bf158SAlex Hornung find_dev_dict(int64_t generation, prop_dictionary_t match_dict, int *idx)
1222e7bf158SAlex Hornung {
1232e7bf158SAlex Hornung struct pdev_array_entry *pae;
1242e7bf158SAlex Hornung prop_array_t pa;
1252e7bf158SAlex Hornung prop_object_iterator_t iter;
1262e7bf158SAlex Hornung prop_dictionary_t dict;
1272e7bf158SAlex Hornung int i = 0;
1282e7bf158SAlex Hornung
1292e7bf158SAlex Hornung if (generation == -1)
1302e7bf158SAlex Hornung pae = pdev_array_entry_get_last();
1312e7bf158SAlex Hornung else
1322e7bf158SAlex Hornung pae = pdev_array_entry_get(generation);
1332e7bf158SAlex Hornung
1342e7bf158SAlex Hornung if (pae == NULL)
1352e7bf158SAlex Hornung return NULL;
1362e7bf158SAlex Hornung
1372e7bf158SAlex Hornung pa = pae->pdev_array;
1382e7bf158SAlex Hornung
1392e7bf158SAlex Hornung iter = prop_array_iterator(pa);
1402e7bf158SAlex Hornung if (iter == NULL) {
1412e7bf158SAlex Hornung pdev_array_entry_unref(pae);
1422e7bf158SAlex Hornung return NULL;
1432e7bf158SAlex Hornung }
1442e7bf158SAlex Hornung
1452e7bf158SAlex Hornung while ((dict = prop_object_iterator_next(iter)) != NULL) {
1462e7bf158SAlex Hornung if (match_dev_dict(dict, match_dict))
1472e7bf158SAlex Hornung break;
1482e7bf158SAlex Hornung ++i;
1492e7bf158SAlex Hornung }
1502e7bf158SAlex Hornung
1512e7bf158SAlex Hornung prop_object_iterator_release(iter);
1522e7bf158SAlex Hornung
1532e7bf158SAlex Hornung if (idx != NULL)
1542e7bf158SAlex Hornung *idx = i;
1552e7bf158SAlex Hornung
1562e7bf158SAlex Hornung pdev_array_entry_unref(pae);
1572e7bf158SAlex Hornung return dict;
1582e7bf158SAlex Hornung }
1592e7bf158SAlex Hornung
1602e7bf158SAlex Hornung void
udev_read_event(int fd)1612e7bf158SAlex Hornung udev_read_event(int fd)
1622e7bf158SAlex Hornung {
1632e7bf158SAlex Hornung struct pdev_array_entry *pae;
1642e7bf158SAlex Hornung prop_dictionary_t dict, evdict, devdict;
1652e7bf158SAlex Hornung prop_number_t pn;
1662e7bf158SAlex Hornung prop_string_t ps;
1672e7bf158SAlex Hornung prop_object_t po;
1682e7bf158SAlex Hornung prop_array_t pa;
1692e7bf158SAlex Hornung char *xml;
1702e7bf158SAlex Hornung int n, idx, evtype;
1712e7bf158SAlex Hornung size_t sz;
1722e7bf158SAlex Hornung
1732e7bf158SAlex Hornung sz = 4096 * 1024;
1742e7bf158SAlex Hornung
1752e7bf158SAlex Hornung xml = malloc(sz); /* 4 MB */
1762e7bf158SAlex Hornung again:
1772e7bf158SAlex Hornung if ((n = read(fd, xml, sz)) <= 0) {
1782e7bf158SAlex Hornung if (errno == ENOMEM) {
1792e7bf158SAlex Hornung sz <<= 2;
180*4634298cSAlex Hornung if ((xml = realloc(xml, sz)) == NULL) {
181*4634298cSAlex Hornung syslog(LOG_ERR, "could not realloc xml memory");
182*4634298cSAlex Hornung return;
183*4634298cSAlex Hornung }
1842e7bf158SAlex Hornung goto again;
1852e7bf158SAlex Hornung }
1862e7bf158SAlex Hornung free(xml);
1872e7bf158SAlex Hornung return;
1882e7bf158SAlex Hornung }
1892e7bf158SAlex Hornung
1902e7bf158SAlex Hornung dict = prop_dictionary_internalize(xml);
1912e7bf158SAlex Hornung free(xml);
1922e7bf158SAlex Hornung if (dict == NULL) {
1932e7bf158SAlex Hornung syslog(LOG_ERR, "internalization of xml failed");
1942e7bf158SAlex Hornung return;
1952e7bf158SAlex Hornung }
1962e7bf158SAlex Hornung
1972e7bf158SAlex Hornung pn = prop_dictionary_get(dict, "evtype");
1982e7bf158SAlex Hornung if (pn == NULL) {
1992e7bf158SAlex Hornung syslog(LOG_ERR, "read_event: no key evtype");
2002e7bf158SAlex Hornung goto out;
2012e7bf158SAlex Hornung }
2022e7bf158SAlex Hornung
2032e7bf158SAlex Hornung evtype = prop_number_integer_value(pn);
2042e7bf158SAlex Hornung
2052e7bf158SAlex Hornung evdict = prop_dictionary_get(dict, "evdict");
2062e7bf158SAlex Hornung if (evdict == NULL) {
2072e7bf158SAlex Hornung syslog(LOG_ERR, "read_event: no key evdict");
2082e7bf158SAlex Hornung goto out;
2092e7bf158SAlex Hornung }
2102e7bf158SAlex Hornung
2112e7bf158SAlex Hornung switch (evtype) {
2122e7bf158SAlex Hornung case UDEV_EVENT_ATTACH:
2132e7bf158SAlex Hornung monitor_queue_event(dict);
2142e7bf158SAlex Hornung pae = pdev_array_entry_get_last();
2152e7bf158SAlex Hornung pa = prop_array_copy(pae->pdev_array);
2162e7bf158SAlex Hornung pdev_array_entry_unref(pae);
2172e7bf158SAlex Hornung if (pa == NULL)
2182e7bf158SAlex Hornung goto out;
2192e7bf158SAlex Hornung prop_array_add(pa, evdict);
2202e7bf158SAlex Hornung pdev_array_entry_insert(pa);
2212e7bf158SAlex Hornung break;
2222e7bf158SAlex Hornung
2232e7bf158SAlex Hornung case UDEV_EVENT_DETACH:
2242e7bf158SAlex Hornung monitor_queue_event(dict);
2252e7bf158SAlex Hornung if ((devdict = find_dev_dict(-1, evdict, &idx)) == NULL)
2262e7bf158SAlex Hornung goto out;
2272e7bf158SAlex Hornung pae = pdev_array_entry_get_last();
2282e7bf158SAlex Hornung pa = prop_array_copy(pae->pdev_array);
2292e7bf158SAlex Hornung pdev_array_entry_unref(pae);
2302e7bf158SAlex Hornung if (pa == NULL)
2312e7bf158SAlex Hornung goto out;
2322e7bf158SAlex Hornung prop_array_remove(pa, idx);
2339ff03f9eSAlex Hornung pdev_array_entry_insert(pa);
2342e7bf158SAlex Hornung break;
2352e7bf158SAlex Hornung
2362e7bf158SAlex Hornung case UDEV_EV_KEY_UPDATE:
2372e7bf158SAlex Hornung if ((devdict = find_dev_dict(-1, evdict, NULL)) == NULL)
2382e7bf158SAlex Hornung goto out;
2392e7bf158SAlex Hornung if ((ps = prop_dictionary_get(evdict, "key")) == NULL)
2402e7bf158SAlex Hornung goto out;
2412e7bf158SAlex Hornung if ((po = prop_dictionary_get(evdict, "value")) == NULL)
2422e7bf158SAlex Hornung goto out;
2432e7bf158SAlex Hornung /* prop_object_retain(po); */ /* not necessary afaik */
2442e7bf158SAlex Hornung prop_dictionary_set(devdict, prop_string_cstring_nocopy(ps), po);
2452e7bf158SAlex Hornung break;
2462e7bf158SAlex Hornung
2472e7bf158SAlex Hornung case UDEV_EV_KEY_REMOVE:
2482e7bf158SAlex Hornung if ((devdict = find_dev_dict(-1, evdict, NULL)) == NULL)
2492e7bf158SAlex Hornung goto out;
2502e7bf158SAlex Hornung if ((ps = prop_dictionary_get(evdict, "key")) == NULL)
2512e7bf158SAlex Hornung goto out;
2522e7bf158SAlex Hornung prop_dictionary_remove(devdict, prop_string_cstring_nocopy(ps));
2532e7bf158SAlex Hornung break;
2542e7bf158SAlex Hornung
2552e7bf158SAlex Hornung default:
2562e7bf158SAlex Hornung syslog(LOG_ERR, "read_event: unknown evtype %d", evtype);
2572e7bf158SAlex Hornung }
2582e7bf158SAlex Hornung
2592e7bf158SAlex Hornung out:
2602e7bf158SAlex Hornung prop_object_release(dict);
2612e7bf158SAlex Hornung return;
2622e7bf158SAlex Hornung }
2632e7bf158SAlex Hornung
2642e7bf158SAlex Hornung prop_array_t
udev_getdevs(int devfd)2652e7bf158SAlex Hornung udev_getdevs(int devfd)
2662e7bf158SAlex Hornung {
2672e7bf158SAlex Hornung prop_dictionary_t pd, rpd;
2682e7bf158SAlex Hornung prop_string_t ps;
2692e7bf158SAlex Hornung prop_array_t pa;
2702e7bf158SAlex Hornung
2712e7bf158SAlex Hornung pd = prop_dictionary_create();
2722e7bf158SAlex Hornung if (pd == NULL) {
2732e7bf158SAlex Hornung err(1, "prop_dictionary_create()");
2742e7bf158SAlex Hornung }
2752e7bf158SAlex Hornung
2762e7bf158SAlex Hornung ps = prop_string_create_cstring("getdevs");
2772e7bf158SAlex Hornung if (ps == NULL) {
2782e7bf158SAlex Hornung prop_object_release(pd);
2792e7bf158SAlex Hornung err(1, "prop_string_create_cstring()");
2802e7bf158SAlex Hornung }
2812e7bf158SAlex Hornung
2822e7bf158SAlex Hornung if (prop_dictionary_set(pd, "command", ps) == false) {
2832e7bf158SAlex Hornung prop_object_release(ps);
2842e7bf158SAlex Hornung prop_object_release(pd);
2852e7bf158SAlex Hornung err(1, "prop_dictionary_set()");
2862e7bf158SAlex Hornung }
2872e7bf158SAlex Hornung
2882e7bf158SAlex Hornung prop_object_release(ps);
2892e7bf158SAlex Hornung
2902e7bf158SAlex Hornung /* Send dictionary to kernel space */
2912e7bf158SAlex Hornung if (prop_dictionary_sendrecv_ioctl(pd, devfd, UDEVPROP, &rpd) != 0)
2922e7bf158SAlex Hornung err(1, "prop_array_recv_ioctl()");
2932e7bf158SAlex Hornung
2942e7bf158SAlex Hornung prop_object_release(pd);
2952e7bf158SAlex Hornung
2962e7bf158SAlex Hornung pa = prop_dictionary_get(rpd, "array");
2972e7bf158SAlex Hornung if (pa == NULL)
2982e7bf158SAlex Hornung goto out;
2992e7bf158SAlex Hornung prop_object_retain(pa);
3002e7bf158SAlex Hornung
3012e7bf158SAlex Hornung out:
3022e7bf158SAlex Hornung prop_object_release(rpd);
3032e7bf158SAlex Hornung return pa;
3042e7bf158SAlex Hornung }
3052e7bf158SAlex Hornung
306dfd5d655SAlex Hornung static void
killed(int sig __unused)307dfd5d655SAlex Hornung killed(int sig __unused)
308dfd5d655SAlex Hornung {
309dfd5d655SAlex Hornung syslog(LOG_ERR, "udevd stopped");
310dfd5d655SAlex Hornung unlink("/var/run/udevd.pid");
3119ff03f9eSAlex Hornung pdev_array_clean();
3127f78ed6cSAlex Hornung exit(0);
313dfd5d655SAlex Hornung }
314dfd5d655SAlex Hornung
3153913f938SAlex Hornung static void
hangup(int sig __unused)3163913f938SAlex Hornung hangup(int sig __unused)
3173913f938SAlex Hornung {
3183913f938SAlex Hornung FILE *pidf;
3193913f938SAlex Hornung int s;
3203913f938SAlex Hornung
3213913f938SAlex Hornung syslog(LOG_ERR, "udevd hangup+resume");
3223913f938SAlex Hornung
3233913f938SAlex Hornung pidf = fopen("/var/run/udevd.pid", "w");
3243913f938SAlex Hornung if (pidf != NULL) {
3253913f938SAlex Hornung fprintf(pidf, "%ld\n", (long)getpid());
3263913f938SAlex Hornung fclose(pidf);
3273913f938SAlex Hornung }
3283913f938SAlex Hornung
3293913f938SAlex Hornung hangup_ongoing = 1;
3303913f938SAlex Hornung close(fds[UDEV_SOCKET_FD_IDX].fd);
3313913f938SAlex Hornung pdev_array_clean();
3323913f938SAlex Hornung s = init_local_server(LISTEN_SOCKET_FILE, SOCK_STREAM, 0);
3333913f938SAlex Hornung if (s < 0)
3343913f938SAlex Hornung err(1, "init_local_server");
3353913f938SAlex Hornung
3363913f938SAlex Hornung fds[UDEV_SOCKET_FD_IDX].fd = s;
3373913f938SAlex Hornung pdev_array_entry_insert(udev_getdevs(udevfd));
3383913f938SAlex Hornung hangup_ongoing = 0;
3393913f938SAlex Hornung }
3403913f938SAlex Hornung
3412e7bf158SAlex Hornung int
ignore_signal(int signum)3422e7bf158SAlex Hornung ignore_signal(int signum)
3432e7bf158SAlex Hornung {
3442e7bf158SAlex Hornung struct sigaction act;
3452e7bf158SAlex Hornung int ret;
3462e7bf158SAlex Hornung
3472e7bf158SAlex Hornung act.sa_handler = SIG_IGN;
3482e7bf158SAlex Hornung sigemptyset(&act.sa_mask);
3492e7bf158SAlex Hornung act.sa_flags = 0;
3502e7bf158SAlex Hornung
3512e7bf158SAlex Hornung ret = sigaction(signum, &act, NULL);
3522e7bf158SAlex Hornung return ret;
3532e7bf158SAlex Hornung }
3542e7bf158SAlex Hornung
355dfd5d655SAlex Hornung static int
set_signal(int signum,sig_t sig_func)3563913f938SAlex Hornung set_signal(int signum, sig_t sig_func)
357dfd5d655SAlex Hornung {
358dfd5d655SAlex Hornung struct sigaction act;
359dfd5d655SAlex Hornung int ret;
360dfd5d655SAlex Hornung
3613913f938SAlex Hornung act.sa_handler = sig_func;
362dfd5d655SAlex Hornung sigemptyset(&act.sa_mask);
363dfd5d655SAlex Hornung act.sa_flags = 0;
364dfd5d655SAlex Hornung
3653913f938SAlex Hornung ret = sigaction(signum, &act, NULL);
366dfd5d655SAlex Hornung return ret;
367dfd5d655SAlex Hornung }
368dfd5d655SAlex Hornung
main(int argc,char * argv[])369ac859449SAntonio Huete Jimenez int main(int argc, char *argv[])
3702e7bf158SAlex Hornung {
3712e7bf158SAlex Hornung int error __unused, i, r, s;
372dfd5d655SAlex Hornung FILE *pidf;
373ac859449SAntonio Huete Jimenez int ch = 0;
374ac859449SAntonio Huete Jimenez
375ac859449SAntonio Huete Jimenez while ((ch = getopt(argc, argv, "d")) != -1) {
376ac859449SAntonio Huete Jimenez switch(ch) {
377ac859449SAntonio Huete Jimenez case 'd':
378ac859449SAntonio Huete Jimenez debugopt = 1;
379ac859449SAntonio Huete Jimenez break;
380ac859449SAntonio Huete Jimenez default:
381ac859449SAntonio Huete Jimenez usage();
382ac859449SAntonio Huete Jimenez /* NOT REACHED */
383ac859449SAntonio Huete Jimenez }
384ac859449SAntonio Huete Jimenez }
385ac859449SAntonio Huete Jimenez argc -= optind;
38689a28649SAntonio Huete Jimenez argv += optind;
3872e7bf158SAlex Hornung
3882e7bf158SAlex Hornung TAILQ_INIT(&pdev_array_list);
3892e7bf158SAlex Hornung TAILQ_INIT(&udev_monitor_list);
3902e7bf158SAlex Hornung
3912e7bf158SAlex Hornung r = ignore_signal(SIGPIPE);
3922e7bf158SAlex Hornung if (r != 0)
3932e7bf158SAlex Hornung err(1, "could not ignore_signal SIGPIPE");
3942e7bf158SAlex Hornung
3952e7bf158SAlex Hornung r = pthread_mutex_init(&(monitor_lock), NULL);
3962e7bf158SAlex Hornung if (r != 0)
3972e7bf158SAlex Hornung err(1, "could not allocate a pthread_mutex");
3982e7bf158SAlex Hornung
3992e7bf158SAlex Hornung if ((udevfd = open(UDEV_DEVICE_PATH, O_RDWR | O_NONBLOCK)) == -1)
4002e7bf158SAlex Hornung err(1, "%s", UDEV_DEVICE_PATH);
4012e7bf158SAlex Hornung unblock_descriptor(udevfd);
4022e7bf158SAlex Hornung
4032e7bf158SAlex Hornung s = init_local_server(LISTEN_SOCKET_FILE, SOCK_STREAM, 0);
4042e7bf158SAlex Hornung if (s < 0)
4052e7bf158SAlex Hornung err(1, "init_local_server");
4062e7bf158SAlex Hornung
407dfd5d655SAlex Hornung pidf = fopen("/var/run/udevd.pid", "w");
4083913f938SAlex Hornung #if 0
409dfd5d655SAlex Hornung if (pidf == NULL)
410dfd5d655SAlex Hornung err(1, "pidfile");
4113913f938SAlex Hornung #endif
412dfd5d655SAlex Hornung
4133913f938SAlex Hornung set_signal(SIGTERM, killed);
4143913f938SAlex Hornung set_signal(SIGHUP, hangup);
415dfd5d655SAlex Hornung
416ac859449SAntonio Huete Jimenez if (debugopt == 0)
4172e7bf158SAlex Hornung if (daemon(0, 0) == -1)
4182e7bf158SAlex Hornung err(1, "daemon");
4192e7bf158SAlex Hornung
4203913f938SAlex Hornung if (pidf != NULL) {
421dfd5d655SAlex Hornung fprintf(pidf, "%ld\n", (long)getpid());
422dfd5d655SAlex Hornung fclose(pidf);
4233913f938SAlex Hornung }
424dfd5d655SAlex Hornung
4252e7bf158SAlex Hornung syslog(LOG_ERR, "udevd started");
4262e7bf158SAlex Hornung
4272e7bf158SAlex Hornung pdev_array_entry_insert(udev_getdevs(udevfd));
4282e7bf158SAlex Hornung
4292e7bf158SAlex Hornung memset(fds, 0 , sizeof(fds));
4302e7bf158SAlex Hornung fds[UDEV_DEVICE_FD_IDX].fd = udevfd;
4312e7bf158SAlex Hornung fds[UDEV_DEVICE_FD_IDX].events = POLLIN;
4322e7bf158SAlex Hornung fds[UDEV_SOCKET_FD_IDX].fd = s;
4332e7bf158SAlex Hornung fds[UDEV_SOCKET_FD_IDX].events = POLLIN | POLLPRI;
4342e7bf158SAlex Hornung
4352e7bf158SAlex Hornung for (;;) {
4362e7bf158SAlex Hornung r = poll(fds, NFDS, -1);
4373913f938SAlex Hornung if (r < 0) {
4383913f938SAlex Hornung if (hangup_ongoing == 0) {
4393913f938SAlex Hornung if (errno == EINTR) {
4403913f938SAlex Hornung usleep(5000);
4413913f938SAlex Hornung continue;
4423913f938SAlex Hornung } else {
4432e7bf158SAlex Hornung err(1, "polling...");
4443913f938SAlex Hornung }
4453913f938SAlex Hornung } else {
4463913f938SAlex Hornung usleep(20000); /* 20 ms */
4473913f938SAlex Hornung continue;
4483913f938SAlex Hornung }
4493913f938SAlex Hornung }
4502e7bf158SAlex Hornung
4512e7bf158SAlex Hornung for (i = 0; (i < NFDS) && (r > 0); i++) {
4522e7bf158SAlex Hornung if (fds[i].revents == 0)
4532e7bf158SAlex Hornung continue;
4542e7bf158SAlex Hornung
4552e7bf158SAlex Hornung --r;
4562e7bf158SAlex Hornung switch (i) {
4572e7bf158SAlex Hornung case UDEV_DEVICE_FD_IDX:
4582e7bf158SAlex Hornung udev_read_event(udevfd);
4592e7bf158SAlex Hornung break;
4602e7bf158SAlex Hornung case UDEV_SOCKET_FD_IDX:
4612e7bf158SAlex Hornung handle_new_connection(s);
4622e7bf158SAlex Hornung break;
4632e7bf158SAlex Hornung default:
4642e7bf158SAlex Hornung break;
4652e7bf158SAlex Hornung }
4662e7bf158SAlex Hornung }
4672e7bf158SAlex Hornung }
4682e7bf158SAlex Hornung
4693913f938SAlex Hornung syslog(LOG_ERR, "udevd is exiting normally");
4702e7bf158SAlex Hornung return 0;
4712e7bf158SAlex Hornung }
472