xref: /freebsd-14.2/sbin/devd/devd.cc (revision 3054f218)
1*3054f218SWarner Losh /*-
2*3054f218SWarner Losh  * Copyright (c) 2002 M. Warner Losh.
3*3054f218SWarner Losh  * All rights reserved.
4*3054f218SWarner Losh  *
5*3054f218SWarner Losh  * Redistribution and use in source and binary forms, with or without
6*3054f218SWarner Losh  * modification, are permitted provided that the following conditions
7*3054f218SWarner Losh  * are met:
8*3054f218SWarner Losh  * 1. Redistributions of source code must retain the above copyright
9*3054f218SWarner Losh  *    notice, this list of conditions and the following disclaimer.
10*3054f218SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
11*3054f218SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
12*3054f218SWarner Losh  *    documentation and/or other materials provided with the distribution.
13*3054f218SWarner Losh  *
14*3054f218SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*3054f218SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*3054f218SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*3054f218SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*3054f218SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*3054f218SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*3054f218SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*3054f218SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*3054f218SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*3054f218SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*3054f218SWarner Losh  * SUCH DAMAGE.
25*3054f218SWarner Losh  */
26*3054f218SWarner Losh 
27*3054f218SWarner Losh /*
28*3054f218SWarner Losh  * DEVD control daemon.
29*3054f218SWarner Losh  */
30*3054f218SWarner Losh 
31*3054f218SWarner Losh // TODO list:
32*3054f218SWarner Losh //	o rewrite the main loop:
33*3054f218SWarner Losh //	  - expand variables
34*3054f218SWarner Losh //	  - find best match
35*3054f218SWarner Losh //	  - execute it.
36*3054f218SWarner Losh //	o need to insert the event_proc structures in order of priority.
37*3054f218SWarner Losh //        bigger numbers mean higher priority.
38*3054f218SWarner Losh //	o devd.conf and devd man pages need a lot of help:
39*3054f218SWarner Losh //	  - devd.conf needs to lose the warning about zone files.
40*3054f218SWarner Losh //	  - devd.conf needs more details on the supported statements.
41*3054f218SWarner Losh //	  - devd.conf needs an example or two.
42*3054f218SWarner Losh 
43*3054f218SWarner Losh #include <sys/cdefs.h>
44*3054f218SWarner Losh __FBSDID("$FreeBSD$");
45*3054f218SWarner Losh 
46*3054f218SWarner Losh #include <sys/param.h>
47*3054f218SWarner Losh #include <sys/types.h>
48*3054f218SWarner Losh 
49*3054f218SWarner Losh #include <dirent.h>
50*3054f218SWarner Losh #include <errno.h>
51*3054f218SWarner Losh #include <err.h>
52*3054f218SWarner Losh #include <fcntl.h>
53*3054f218SWarner Losh #include <stdlib.h>
54*3054f218SWarner Losh #include <stdio.h>
55*3054f218SWarner Losh #include <string.h>
56*3054f218SWarner Losh #include <unistd.h>
57*3054f218SWarner Losh 
58*3054f218SWarner Losh #include <map>
59*3054f218SWarner Losh #include <string>
60*3054f218SWarner Losh #include <vector>
61*3054f218SWarner Losh 
62*3054f218SWarner Losh #include "devd.h"
63*3054f218SWarner Losh 
64*3054f218SWarner Losh #define CF "/etc/devd.conf"
65*3054f218SWarner Losh 
66*3054f218SWarner Losh using namespace std;
67*3054f218SWarner Losh 
68*3054f218SWarner Losh extern FILE *yyin;
69*3054f218SWarner Losh extern int lineno;
70*3054f218SWarner Losh 
71*3054f218SWarner Losh int dflag;
72*3054f218SWarner Losh int romeo_must_die = 0;
73*3054f218SWarner Losh 
74*3054f218SWarner Losh static void event_loop(void);
75*3054f218SWarner Losh static void usage(void);
76*3054f218SWarner Losh 
77*3054f218SWarner Losh class config;
78*3054f218SWarner Losh 
79*3054f218SWarner Losh 
80*3054f218SWarner Losh class var_list
81*3054f218SWarner Losh {
82*3054f218SWarner Losh public:
83*3054f218SWarner Losh 	var_list() {}
84*3054f218SWarner Losh 	virtual ~var_list() {}
85*3054f218SWarner Losh 	void set_variable(const string &var, const string &val);
86*3054f218SWarner Losh 	const string &get_variable(const string &var) const;
87*3054f218SWarner Losh 	bool is_set(const string &var) const;
88*3054f218SWarner Losh 	static const string bogus;
89*3054f218SWarner Losh 	static const string nothing;
90*3054f218SWarner Losh private:
91*3054f218SWarner Losh 	map<string, string> _vars;
92*3054f218SWarner Losh };
93*3054f218SWarner Losh 
94*3054f218SWarner Losh class eps
95*3054f218SWarner Losh {
96*3054f218SWarner Losh public:
97*3054f218SWarner Losh 	eps() {}
98*3054f218SWarner Losh 	virtual ~eps() {}
99*3054f218SWarner Losh 	virtual bool do_match(config &) = 0;
100*3054f218SWarner Losh 	virtual bool do_action(config &) = 0;
101*3054f218SWarner Losh };
102*3054f218SWarner Losh 
103*3054f218SWarner Losh class match : public eps
104*3054f218SWarner Losh {
105*3054f218SWarner Losh public:
106*3054f218SWarner Losh 	match(const char *var, const char *re);
107*3054f218SWarner Losh 	virtual ~match();
108*3054f218SWarner Losh 	virtual bool do_match(config &);
109*3054f218SWarner Losh 	virtual bool do_action(config &) { return true; }
110*3054f218SWarner Losh private:
111*3054f218SWarner Losh 	string _var;
112*3054f218SWarner Losh 	string _re;
113*3054f218SWarner Losh };
114*3054f218SWarner Losh 
115*3054f218SWarner Losh class action : public eps
116*3054f218SWarner Losh {
117*3054f218SWarner Losh public:
118*3054f218SWarner Losh 	action(const char *cmd);
119*3054f218SWarner Losh 	virtual ~action();
120*3054f218SWarner Losh 	virtual bool do_match(config &) { return true; }
121*3054f218SWarner Losh 	virtual bool do_action(config &);
122*3054f218SWarner Losh private:
123*3054f218SWarner Losh 	string _cmd;
124*3054f218SWarner Losh };
125*3054f218SWarner Losh 
126*3054f218SWarner Losh class event_proc
127*3054f218SWarner Losh {
128*3054f218SWarner Losh public:
129*3054f218SWarner Losh 	event_proc();
130*3054f218SWarner Losh 	virtual ~event_proc();
131*3054f218SWarner Losh 	int get_priority() { return (_prio); }
132*3054f218SWarner Losh 	void set_priority(int prio) { _prio = prio; }
133*3054f218SWarner Losh 	void add(eps *);
134*3054f218SWarner Losh 	bool matches(config &);
135*3054f218SWarner Losh 	bool run(config &);
136*3054f218SWarner Losh private:
137*3054f218SWarner Losh 	int _prio;
138*3054f218SWarner Losh 	vector<eps *> _epsvec;
139*3054f218SWarner Losh };
140*3054f218SWarner Losh 
141*3054f218SWarner Losh class config
142*3054f218SWarner Losh {
143*3054f218SWarner Losh public:
144*3054f218SWarner Losh 	config() : _pidfile("") { push_var_table(); }
145*3054f218SWarner Losh 	virtual ~config() { reset(); }
146*3054f218SWarner Losh 	void add_attach(int, event_proc *);
147*3054f218SWarner Losh 	void add_detach(int, event_proc *);
148*3054f218SWarner Losh 	void add_directory(const char *);
149*3054f218SWarner Losh 	void add_nomatch(int, event_proc *);
150*3054f218SWarner Losh 	void set_pidfile(const char *);
151*3054f218SWarner Losh 	void reset();
152*3054f218SWarner Losh 	void parse();
153*3054f218SWarner Losh 	void drop_pidfile();
154*3054f218SWarner Losh 	void push_var_table();
155*3054f218SWarner Losh 	void pop_var_table();
156*3054f218SWarner Losh 	void set_variable(const char *var, const char *val);
157*3054f218SWarner Losh 	const string &get_variable(const string &var);
158*3054f218SWarner Losh 	const string &expand_string(const string &var);
159*3054f218SWarner Losh protected:
160*3054f218SWarner Losh 	void parse_one_file(const char *fn);
161*3054f218SWarner Losh 	void parse_files_in_dir(const char *dirname);
162*3054f218SWarner Losh private:
163*3054f218SWarner Losh 	vector<string> _dir_list;
164*3054f218SWarner Losh 	string _pidfile;
165*3054f218SWarner Losh 	vector<var_list *> _var_list_table;
166*3054f218SWarner Losh 	vector<event_proc *> _attach_list;
167*3054f218SWarner Losh 	vector<event_proc *> _detach_list;
168*3054f218SWarner Losh 	vector<event_proc *> _nomatch_list;
169*3054f218SWarner Losh };
170*3054f218SWarner Losh 
171*3054f218SWarner Losh config cfg;
172*3054f218SWarner Losh 
173*3054f218SWarner Losh event_proc::event_proc() : _prio(-1)
174*3054f218SWarner Losh {
175*3054f218SWarner Losh 	// nothing
176*3054f218SWarner Losh }
177*3054f218SWarner Losh 
178*3054f218SWarner Losh event_proc::~event_proc()
179*3054f218SWarner Losh {
180*3054f218SWarner Losh 	vector<eps *>::const_iterator i;
181*3054f218SWarner Losh 
182*3054f218SWarner Losh 	for (i = _epsvec.begin(); i != _epsvec.end(); i++)
183*3054f218SWarner Losh 		delete *i;
184*3054f218SWarner Losh 	_epsvec.clear();
185*3054f218SWarner Losh }
186*3054f218SWarner Losh 
187*3054f218SWarner Losh void
188*3054f218SWarner Losh event_proc::add(eps *eps)
189*3054f218SWarner Losh {
190*3054f218SWarner Losh 	_epsvec.push_back(eps);
191*3054f218SWarner Losh }
192*3054f218SWarner Losh 
193*3054f218SWarner Losh bool
194*3054f218SWarner Losh event_proc::matches(config &c)
195*3054f218SWarner Losh {
196*3054f218SWarner Losh 	vector<eps *>::const_iterator i;
197*3054f218SWarner Losh 
198*3054f218SWarner Losh 	for (i = _epsvec.begin(); i != _epsvec.end(); i++)
199*3054f218SWarner Losh 		if (!(*i)->do_match(c))
200*3054f218SWarner Losh 			return (false);
201*3054f218SWarner Losh 	return (true);
202*3054f218SWarner Losh }
203*3054f218SWarner Losh 
204*3054f218SWarner Losh bool
205*3054f218SWarner Losh event_proc::run(config &c)
206*3054f218SWarner Losh {
207*3054f218SWarner Losh 	vector<eps *>::const_iterator i;
208*3054f218SWarner Losh 
209*3054f218SWarner Losh 	for (i = _epsvec.begin(); i != _epsvec.end(); i++)
210*3054f218SWarner Losh 		if (!(*i)->do_action(c))
211*3054f218SWarner Losh 			return (false);
212*3054f218SWarner Losh 	return (true);
213*3054f218SWarner Losh }
214*3054f218SWarner Losh 
215*3054f218SWarner Losh action::action(const char *cmd)
216*3054f218SWarner Losh 	: _cmd(cmd)
217*3054f218SWarner Losh {
218*3054f218SWarner Losh 	// nothing
219*3054f218SWarner Losh }
220*3054f218SWarner Losh 
221*3054f218SWarner Losh action::~action()
222*3054f218SWarner Losh {
223*3054f218SWarner Losh 	// nothing
224*3054f218SWarner Losh }
225*3054f218SWarner Losh 
226*3054f218SWarner Losh bool
227*3054f218SWarner Losh action::do_action(config &)
228*3054f218SWarner Losh {
229*3054f218SWarner Losh 	// this is lame because we don't expand variables.
230*3054f218SWarner Losh 	// xxx
231*3054f218SWarner Losh 	::system(_cmd.c_str());
232*3054f218SWarner Losh 	return (true);
233*3054f218SWarner Losh }
234*3054f218SWarner Losh 
235*3054f218SWarner Losh match::match(const char *var, const char *re)
236*3054f218SWarner Losh 	: _var(var), _re(re)
237*3054f218SWarner Losh {
238*3054f218SWarner Losh 	// nothing
239*3054f218SWarner Losh }
240*3054f218SWarner Losh 
241*3054f218SWarner Losh match::~match()
242*3054f218SWarner Losh {
243*3054f218SWarner Losh 	// nothing
244*3054f218SWarner Losh }
245*3054f218SWarner Losh 
246*3054f218SWarner Losh bool
247*3054f218SWarner Losh match::do_match(config &)
248*3054f218SWarner Losh {
249*3054f218SWarner Losh 	// XXX
250*3054f218SWarner Losh 	return false;
251*3054f218SWarner Losh }
252*3054f218SWarner Losh 
253*3054f218SWarner Losh const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_";
254*3054f218SWarner Losh const string var_list::nothing = "";
255*3054f218SWarner Losh 
256*3054f218SWarner Losh const string &
257*3054f218SWarner Losh var_list::get_variable(const string &var) const
258*3054f218SWarner Losh {
259*3054f218SWarner Losh 	map<string, string>::const_iterator i;
260*3054f218SWarner Losh 
261*3054f218SWarner Losh 	i = _vars.find(var);
262*3054f218SWarner Losh 	if (i == _vars.end())
263*3054f218SWarner Losh 		return var_list::bogus;
264*3054f218SWarner Losh 	return (i->second);
265*3054f218SWarner Losh }
266*3054f218SWarner Losh 
267*3054f218SWarner Losh bool
268*3054f218SWarner Losh var_list::is_set(const string &var) const
269*3054f218SWarner Losh {
270*3054f218SWarner Losh 	return (_vars.find(var) != _vars.end());
271*3054f218SWarner Losh }
272*3054f218SWarner Losh 
273*3054f218SWarner Losh void
274*3054f218SWarner Losh var_list::set_variable(const string &var, const string &val)
275*3054f218SWarner Losh {
276*3054f218SWarner Losh 	_vars[var] = val;
277*3054f218SWarner Losh }
278*3054f218SWarner Losh 
279*3054f218SWarner Losh void
280*3054f218SWarner Losh config::reset(void)
281*3054f218SWarner Losh {
282*3054f218SWarner Losh 	_dir_list.clear();
283*3054f218SWarner Losh 	_var_list_table.clear();
284*3054f218SWarner Losh 	// XXX need to cleanup _{attach,detach,nomatch}_list
285*3054f218SWarner Losh }
286*3054f218SWarner Losh 
287*3054f218SWarner Losh void
288*3054f218SWarner Losh config::parse_one_file(const char *fn)
289*3054f218SWarner Losh {
290*3054f218SWarner Losh 	if (dflag)
291*3054f218SWarner Losh 		printf("Parsing %s\n", fn);
292*3054f218SWarner Losh 	yyin = fopen(fn, "r");
293*3054f218SWarner Losh 	if (yyin == NULL)
294*3054f218SWarner Losh 		err(1, "Cannot open config file %s", fn);
295*3054f218SWarner Losh 	if (yyparse() != 0)
296*3054f218SWarner Losh 		errx(1, "Cannot parse %s at line %d", fn, lineno);
297*3054f218SWarner Losh 	fclose(yyin);
298*3054f218SWarner Losh }
299*3054f218SWarner Losh 
300*3054f218SWarner Losh void
301*3054f218SWarner Losh config::parse_files_in_dir(const char *dirname)
302*3054f218SWarner Losh {
303*3054f218SWarner Losh 	DIR *dirp;
304*3054f218SWarner Losh 	struct dirent *dp;
305*3054f218SWarner Losh 	char path[PATH_MAX];
306*3054f218SWarner Losh 
307*3054f218SWarner Losh 	if (dflag)
308*3054f218SWarner Losh 		printf("Parsing files in %s\n", dirname);
309*3054f218SWarner Losh 	dirp = opendir(dirname);
310*3054f218SWarner Losh 	if (dirp == NULL)
311*3054f218SWarner Losh 		return;
312*3054f218SWarner Losh 	readdir(dirp);		/* Skip . */
313*3054f218SWarner Losh 	readdir(dirp);		/* Skip .. */
314*3054f218SWarner Losh 	while ((dp = readdir(dirp)) != NULL) {
315*3054f218SWarner Losh 		if (strcmp(dp->d_name + dp->d_namlen - 5, ".conf") == 0) {
316*3054f218SWarner Losh 			snprintf(path, sizeof(path), "%s/%s",
317*3054f218SWarner Losh 			    dirname, dp->d_name);
318*3054f218SWarner Losh 			parse_one_file(path);
319*3054f218SWarner Losh 		}
320*3054f218SWarner Losh 	}
321*3054f218SWarner Losh }
322*3054f218SWarner Losh 
323*3054f218SWarner Losh void
324*3054f218SWarner Losh config::parse(void)
325*3054f218SWarner Losh {
326*3054f218SWarner Losh 	vector<string>::const_iterator i;
327*3054f218SWarner Losh 
328*3054f218SWarner Losh 	parse_one_file(CF);
329*3054f218SWarner Losh 	for (i = _dir_list.begin(); i != _dir_list.end(); i++)
330*3054f218SWarner Losh 		parse_files_in_dir((*i).c_str());
331*3054f218SWarner Losh }
332*3054f218SWarner Losh 
333*3054f218SWarner Losh void
334*3054f218SWarner Losh config::drop_pidfile()
335*3054f218SWarner Losh {
336*3054f218SWarner Losh 	FILE *fp;
337*3054f218SWarner Losh 
338*3054f218SWarner Losh 	if (_pidfile == "")
339*3054f218SWarner Losh 		return;
340*3054f218SWarner Losh 	fp = fopen(_pidfile.c_str(), "w");
341*3054f218SWarner Losh 	if (fp == NULL)
342*3054f218SWarner Losh 		return;
343*3054f218SWarner Losh 	fprintf(fp, "%d\n", getpid());
344*3054f218SWarner Losh 	fclose(fp);
345*3054f218SWarner Losh }
346*3054f218SWarner Losh 
347*3054f218SWarner Losh void
348*3054f218SWarner Losh config::add_attach(int prio, event_proc *p)
349*3054f218SWarner Losh {
350*3054f218SWarner Losh 	p->set_priority(prio);
351*3054f218SWarner Losh 	_attach_list.push_back(p);
352*3054f218SWarner Losh }
353*3054f218SWarner Losh 
354*3054f218SWarner Losh void
355*3054f218SWarner Losh config::add_detach(int prio, event_proc *p)
356*3054f218SWarner Losh {
357*3054f218SWarner Losh 	p->set_priority(prio);
358*3054f218SWarner Losh 	_detach_list.push_back(p);
359*3054f218SWarner Losh }
360*3054f218SWarner Losh 
361*3054f218SWarner Losh void
362*3054f218SWarner Losh config::add_directory(const char *dir)
363*3054f218SWarner Losh {
364*3054f218SWarner Losh 	_dir_list.push_back(string(dir));
365*3054f218SWarner Losh }
366*3054f218SWarner Losh 
367*3054f218SWarner Losh void
368*3054f218SWarner Losh config::add_nomatch(int prio, event_proc *p)
369*3054f218SWarner Losh {
370*3054f218SWarner Losh 	p->set_priority(prio);
371*3054f218SWarner Losh 	_nomatch_list.push_back(p);
372*3054f218SWarner Losh }
373*3054f218SWarner Losh 
374*3054f218SWarner Losh void
375*3054f218SWarner Losh config::set_pidfile(const char *fn)
376*3054f218SWarner Losh {
377*3054f218SWarner Losh 	_pidfile = string(fn);
378*3054f218SWarner Losh }
379*3054f218SWarner Losh 
380*3054f218SWarner Losh void
381*3054f218SWarner Losh config::push_var_table()
382*3054f218SWarner Losh {
383*3054f218SWarner Losh 	var_list *vl;
384*3054f218SWarner Losh 
385*3054f218SWarner Losh 	vl = new var_list();
386*3054f218SWarner Losh 	_var_list_table.push_back(vl);
387*3054f218SWarner Losh }
388*3054f218SWarner Losh 
389*3054f218SWarner Losh void
390*3054f218SWarner Losh config::pop_var_table()
391*3054f218SWarner Losh {
392*3054f218SWarner Losh 	delete _var_list_table.back();
393*3054f218SWarner Losh 	_var_list_table.pop_back();
394*3054f218SWarner Losh }
395*3054f218SWarner Losh 
396*3054f218SWarner Losh void
397*3054f218SWarner Losh config::set_variable(const char *var, const char *val)
398*3054f218SWarner Losh {
399*3054f218SWarner Losh 	_var_list_table.back()->set_variable(var, val);
400*3054f218SWarner Losh }
401*3054f218SWarner Losh 
402*3054f218SWarner Losh const string &
403*3054f218SWarner Losh config::get_variable(const string &var)
404*3054f218SWarner Losh {
405*3054f218SWarner Losh 	vector<var_list *>::reverse_iterator i;
406*3054f218SWarner Losh 
407*3054f218SWarner Losh 	for (i = _var_list_table.rbegin(); i != _var_list_table.rend(); i++) {
408*3054f218SWarner Losh 		if ((*i)->is_set(var))
409*3054f218SWarner Losh 			return (var);
410*3054f218SWarner Losh 	}
411*3054f218SWarner Losh 	return (var_list::nothing);
412*3054f218SWarner Losh }
413*3054f218SWarner Losh 
414*3054f218SWarner Losh const string &
415*3054f218SWarner Losh config::expand_string(const string &)
416*3054f218SWarner Losh {
417*3054f218SWarner Losh 	return var_list::bogus;
418*3054f218SWarner Losh }
419*3054f218SWarner Losh 
420*3054f218SWarner Losh 
421*3054f218SWarner Losh static void
422*3054f218SWarner Losh process_event(const char *buffer)
423*3054f218SWarner Losh {
424*3054f218SWarner Losh 	char type;
425*3054f218SWarner Losh 	char cmd[1024];
426*3054f218SWarner Losh 	char *sp;
427*3054f218SWarner Losh 
428*3054f218SWarner Losh 	// XXX should involve config
429*3054f218SWarner Losh 	// XXX and set some variables
430*3054f218SWarner Losh 	// XXX run the list and so forth
431*3054f218SWarner Losh 
432*3054f218SWarner Losh 	// Ignore unknown devices for now.
433*3054f218SWarner Losh 	if (*buffer == '?')
434*3054f218SWarner Losh 		return;
435*3054f218SWarner Losh 	type = *buffer++;
436*3054f218SWarner Losh 	sp = strchr(buffer, ' ');
437*3054f218SWarner Losh 	if (sp == NULL)
438*3054f218SWarner Losh 		return;	/* Can't happen? */
439*3054f218SWarner Losh 	*sp = '\0';
440*3054f218SWarner Losh 	snprintf(cmd, sizeof(cmd), "/etc/devd-generic %s %s", buffer,
441*3054f218SWarner Losh 	    type == '+' ? "start" : "stop");
442*3054f218SWarner Losh 	if (dflag)
443*3054f218SWarner Losh 		printf("Trying '%s'\n", cmd);
444*3054f218SWarner Losh 	system(cmd);
445*3054f218SWarner Losh }
446*3054f218SWarner Losh 
447*3054f218SWarner Losh static void
448*3054f218SWarner Losh event_loop(void)
449*3054f218SWarner Losh {
450*3054f218SWarner Losh 	int rv;
451*3054f218SWarner Losh 	int fd;
452*3054f218SWarner Losh 	char buffer[DEVCTL_MAXBUF];
453*3054f218SWarner Losh 
454*3054f218SWarner Losh 	fd = open(PATH_DEVCTL, O_RDONLY);
455*3054f218SWarner Losh 	if (fd == -1)
456*3054f218SWarner Losh 		err(1, "Can't open devctl");
457*3054f218SWarner Losh 	if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0)
458*3054f218SWarner Losh 		err(1, "Can't set close-on-exec flag");
459*3054f218SWarner Losh 	while (1) {
460*3054f218SWarner Losh 		if (romeo_must_die)
461*3054f218SWarner Losh 			break;
462*3054f218SWarner Losh 		rv = read(fd, buffer, sizeof(buffer) - 1);
463*3054f218SWarner Losh 		if (rv > 0) {
464*3054f218SWarner Losh 			buffer[rv] = '\0';
465*3054f218SWarner Losh 			while (buffer[--rv] == '\n')
466*3054f218SWarner Losh 				buffer[rv] = '\0';
467*3054f218SWarner Losh 			process_event(buffer);
468*3054f218SWarner Losh 		} else if (rv < 0) {
469*3054f218SWarner Losh 			if (errno != EINTR)
470*3054f218SWarner Losh 				break;
471*3054f218SWarner Losh 		} else {
472*3054f218SWarner Losh 			/* EOF */
473*3054f218SWarner Losh 			break;
474*3054f218SWarner Losh 		}
475*3054f218SWarner Losh 	}
476*3054f218SWarner Losh 	close(fd);
477*3054f218SWarner Losh }
478*3054f218SWarner Losh 
479*3054f218SWarner Losh /*
480*3054f218SWarner Losh  * functions that the parser uses.
481*3054f218SWarner Losh  */
482*3054f218SWarner Losh void
483*3054f218SWarner Losh add_attach(int prio, event_proc *p)
484*3054f218SWarner Losh {
485*3054f218SWarner Losh 	cfg.add_attach(prio, p);
486*3054f218SWarner Losh }
487*3054f218SWarner Losh 
488*3054f218SWarner Losh void
489*3054f218SWarner Losh add_detach(int prio, event_proc *p)
490*3054f218SWarner Losh {
491*3054f218SWarner Losh 	cfg.add_detach(prio, p);
492*3054f218SWarner Losh }
493*3054f218SWarner Losh 
494*3054f218SWarner Losh void
495*3054f218SWarner Losh add_directory(const char *dir)
496*3054f218SWarner Losh {
497*3054f218SWarner Losh 	cfg.add_directory(dir);
498*3054f218SWarner Losh 	free(const_cast<char *>(dir));
499*3054f218SWarner Losh }
500*3054f218SWarner Losh 
501*3054f218SWarner Losh void
502*3054f218SWarner Losh add_nomatch(int prio, event_proc *p)
503*3054f218SWarner Losh {
504*3054f218SWarner Losh 	cfg.add_nomatch(prio, p);
505*3054f218SWarner Losh }
506*3054f218SWarner Losh 
507*3054f218SWarner Losh event_proc *
508*3054f218SWarner Losh add_to_event_proc(event_proc *ep, eps *eps)
509*3054f218SWarner Losh {
510*3054f218SWarner Losh 	if (ep == NULL)
511*3054f218SWarner Losh 		ep = new event_proc();
512*3054f218SWarner Losh 	ep->add(eps);
513*3054f218SWarner Losh 	return (ep);
514*3054f218SWarner Losh }
515*3054f218SWarner Losh 
516*3054f218SWarner Losh eps *
517*3054f218SWarner Losh new_action(const char *cmd)
518*3054f218SWarner Losh {
519*3054f218SWarner Losh 	eps *e = new action(cmd);
520*3054f218SWarner Losh 	free(const_cast<char *>(cmd));
521*3054f218SWarner Losh 	return (e);
522*3054f218SWarner Losh }
523*3054f218SWarner Losh 
524*3054f218SWarner Losh eps *
525*3054f218SWarner Losh new_match(const char *var, const char *re)
526*3054f218SWarner Losh {
527*3054f218SWarner Losh 	eps *e = new match(var, re);
528*3054f218SWarner Losh 	free(const_cast<char *>(var));
529*3054f218SWarner Losh 	free(const_cast<char *>(re));
530*3054f218SWarner Losh 	return (e);
531*3054f218SWarner Losh }
532*3054f218SWarner Losh 
533*3054f218SWarner Losh void
534*3054f218SWarner Losh set_pidfile(const char *name)
535*3054f218SWarner Losh {
536*3054f218SWarner Losh 	cfg.set_pidfile(name);
537*3054f218SWarner Losh 	free(const_cast<char *>(name));
538*3054f218SWarner Losh }
539*3054f218SWarner Losh 
540*3054f218SWarner Losh void
541*3054f218SWarner Losh set_variable(const char *var, const char *val)
542*3054f218SWarner Losh {
543*3054f218SWarner Losh 	cfg.set_variable(var, val);
544*3054f218SWarner Losh 	free(const_cast<char *>(var));
545*3054f218SWarner Losh 	free(const_cast<char *>(val));
546*3054f218SWarner Losh }
547*3054f218SWarner Losh 
548*3054f218SWarner Losh 
549*3054f218SWarner Losh 
550*3054f218SWarner Losh static void
551*3054f218SWarner Losh gensighand(int)
552*3054f218SWarner Losh {
553*3054f218SWarner Losh 	romeo_must_die++;
554*3054f218SWarner Losh 	_exit(0);
555*3054f218SWarner Losh }
556*3054f218SWarner Losh 
557*3054f218SWarner Losh static void
558*3054f218SWarner Losh usage()
559*3054f218SWarner Losh {
560*3054f218SWarner Losh 	fprintf(stderr, "usage: %s [-d]", getprogname());
561*3054f218SWarner Losh 	exit(1);
562*3054f218SWarner Losh }
563*3054f218SWarner Losh 
564*3054f218SWarner Losh /*
565*3054f218SWarner Losh  * main
566*3054f218SWarner Losh  */
567*3054f218SWarner Losh int
568*3054f218SWarner Losh main(int argc, char **argv)
569*3054f218SWarner Losh {
570*3054f218SWarner Losh 	int ch;
571*3054f218SWarner Losh 
572*3054f218SWarner Losh 	while ((ch = getopt(argc, argv, "d")) != -1) {
573*3054f218SWarner Losh 		switch (ch) {
574*3054f218SWarner Losh 		case 'd':
575*3054f218SWarner Losh 			dflag++;
576*3054f218SWarner Losh 			break;
577*3054f218SWarner Losh 		default:
578*3054f218SWarner Losh 			usage();
579*3054f218SWarner Losh 		}
580*3054f218SWarner Losh 	}
581*3054f218SWarner Losh 
582*3054f218SWarner Losh 	cfg.parse();
583*3054f218SWarner Losh 	if (!dflag)
584*3054f218SWarner Losh 		daemon(0, 0);
585*3054f218SWarner Losh 	cfg.drop_pidfile();
586*3054f218SWarner Losh 	signal(SIGHUP, gensighand);
587*3054f218SWarner Losh 	signal(SIGINT, gensighand);
588*3054f218SWarner Losh 	signal(SIGTERM, gensighand);
589*3054f218SWarner Losh 	event_loop();
590*3054f218SWarner Losh 	return (0);
591*3054f218SWarner Losh }
592