xref: /dflybsd-src/sbin/udevd/udevd.c (revision 0c8103dd622e5016512e2eedb2ceb865982089a5)
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