1 /*
2  * libdpkg - Debian packaging suite library routines
3  * triglib.c - trigger handling
4  *
5  * Copyright © 2007 Canonical Ltd
6  * Written by Ian Jackson <ijackson@chiark.greenend.org.uk>
7  * Copyright © 2008-2015 Guillem Jover <guillem@debian.org>
8  *
9  * This is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21  */
22 
23 #include <config.h>
24 #include <compat.h>
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 
33 #include <dpkg/i18n.h>
34 #include <dpkg/c-ctype.h>
35 #include <dpkg/dpkg.h>
36 #include <dpkg/dpkg-db.h>
37 #include <dpkg/pkg.h>
38 #include <dpkg/dlist.h>
39 #include <dpkg/dir.h>
40 #include <dpkg/pkg-spec.h>
41 #include <dpkg/trigdeferred.h>
42 #include <dpkg/triglib.h>
43 
44 /*========== Recording triggers. ==========*/
45 
46 static char *triggersdir, *triggersfilefile;
47 
48 static char *
trig_get_filename(const char * dir,const char * filename)49 trig_get_filename(const char *dir, const char *filename)
50 {
51 	return str_fmt("%s/%s", dir, filename);
52 }
53 
54 static struct trig_hooks trigh;
55 
56 /*---------- Noting trigger activation in memory. ----------*/
57 
58 /*
59  * Called via trig_*activate* et al from:
60  *   - trig_incorporate: reading of Unincorp (explicit trigger activations)
61  *   - various places: processing start (‘activate’ in triggers ci file)
62  *   - namenodetouse: file triggers during unpack / remove
63  *   - deferred_configure: file triggers during config file processing
64  *
65  * Not called from trig_transitional_activation; that runs
66  * trig_note_pend directly which means that (a) awaiters are not
67  * recorded (how would we know?) and (b) we don't enqueue them for
68  * deferred processing in this run.
69  *
70  * We add the trigger to Triggers-Pending first. This makes it
71  * harder to get into the state where Triggers-Awaited for aw lists
72  * pend but Triggers-Pending for pend is empty. (See also the
73  * comment in deppossi_ok_found regarding this situation.)
74  */
75 
76 /*
77  * aw might be NULL.
78  * trig is not copied!
79  */
80 static void
trig_record_activation(struct pkginfo * pend,struct pkginfo * aw,const char * trig)81 trig_record_activation(struct pkginfo *pend, struct pkginfo *aw, const char *trig)
82 {
83 	if (pend->status < PKG_STAT_TRIGGERSAWAITED)
84 		return; /* Not interested then. */
85 
86 	if (trig_note_pend(pend, trig))
87 		modstatdb_note_ifwrite(pend);
88 
89 	if (trigh.enqueue_deferred)
90 		trigh.enqueue_deferred(pend);
91 
92 	if (aw && pend->status > PKG_STAT_CONFIGFILES)
93 		if (trig_note_aw(pend, aw)) {
94 			if (aw->status > PKG_STAT_TRIGGERSAWAITED)
95 				pkg_set_status(aw, PKG_STAT_TRIGGERSAWAITED);
96 			modstatdb_note_ifwrite(aw);
97 		}
98 }
99 
100 void
trig_clear_awaiters(struct pkginfo * notpend)101 trig_clear_awaiters(struct pkginfo *notpend)
102 {
103 	struct trigaw *ta;
104 	struct pkginfo *aw;
105 
106 	if (notpend->trigpend_head)
107 		internerr("package %s has pending triggers",
108 		          pkg_name(notpend, pnaw_always));
109 
110 	ta = notpend->othertrigaw_head;
111 	notpend->othertrigaw_head = NULL;
112 	for (; ta; ta = ta->samepend_next) {
113 		aw = ta->aw;
114 		if (!aw)
115 			continue;
116 		LIST_UNLINK_PART(aw->trigaw, ta, sameaw);
117 		if (!aw->trigaw.head && aw->status == PKG_STAT_TRIGGERSAWAITED) {
118 			if (aw->trigpend_head)
119 				pkg_set_status(aw, PKG_STAT_TRIGGERSPENDING);
120 			else
121 				pkg_set_status(aw, PKG_STAT_INSTALLED);
122 			modstatdb_note(aw);
123 		}
124 	}
125 }
126 
127 /*
128  * Fix up packages in state triggers-awaited w/o the corresponding package
129  * with pending triggers. This can happen when dpkg was interrupted
130  * while in modstatdb_note, and the package in triggers-pending had its
131  * state modified but dpkg could not finish clearing the awaiters.
132  *
133  * XXX: Possibly get rid of some of the checks done somewhere else for
134  *      this condition at run-time.
135  */
136 void
trig_fixup_awaiters(enum modstatdb_rw cstatus)137 trig_fixup_awaiters(enum modstatdb_rw cstatus)
138 {
139 	if (cstatus < msdbrw_write)
140 		return;
141 
142 	trig_awaited_pend_foreach(trig_clear_awaiters);
143 	trig_awaited_pend_free();
144 }
145 
146 /*---------- Generalized handling of trigger kinds. ----------*/
147 
148 struct trigkindinfo {
149 	/* Only for trig_activate_start. */
150 	void (*activate_start)(void);
151 
152 	/* Rest are for everyone: */
153 	void (*activate_awaiter)(struct pkginfo *pkg /* may be NULL */);
154 	void (*activate_done)(void);
155 	void (*interest_change)(const char *name, struct pkginfo *pkg,
156 	                        struct pkgbin *pkgbin,
157 	                        int signum, enum trig_options opts);
158 };
159 
160 static const struct trigkindinfo tki_explicit, tki_file, tki_unknown;
161 static const struct trigkindinfo *dtki;
162 
163 /* As passed into activate_start. */
164 static char *trig_activating_name;
165 
166 static const struct trigkindinfo *
trig_classify_byname(const char * name)167 trig_classify_byname(const char *name)
168 {
169 	if (name[0] == '/') {
170 		const char *slash;
171 
172 		slash = name;
173 		while (slash) {
174 			if (slash[1] == '\0' || slash[1] == '/')
175 				goto invalid;
176 
177 			slash = strchr(slash + 2, '/');
178 		}
179 		return &tki_file;
180 	}
181 
182 	if (!pkg_name_is_illegal(name) && !strchr(name, '_'))
183 		return &tki_explicit;
184 
185 invalid:
186 	return &tki_unknown;
187 }
188 
189 /*
190  * Calling sequence is:
191  *  trig_activate_start(triggername);
192  *  dtki->activate_awaiter(awaiting_package); } zero or more times
193  *  dtki->activate_awaiter(NULL);             }  in any order
194  *  dtki->activate_done();
195  */
196 static void
trig_activate_start(const char * name)197 trig_activate_start(const char *name)
198 {
199 	dtki = trig_classify_byname(name);
200 	trig_activating_name = nfstrsave(name);
201 	dtki->activate_start();
202 }
203 
204 /*---------- Unknown trigger kinds. ----------*/
205 
206 static void
trk_unknown_activate_start(void)207 trk_unknown_activate_start(void)
208 {
209 }
210 
211 static void
trk_unknown_activate_awaiter(struct pkginfo * aw)212 trk_unknown_activate_awaiter(struct pkginfo *aw)
213 {
214 }
215 
216 static void
trk_unknown_activate_done(void)217 trk_unknown_activate_done(void)
218 {
219 }
220 
221 static void DPKG_ATTR_NORET
trk_unknown_interest_change(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,int signum,enum trig_options opts)222 trk_unknown_interest_change(const char *trig, struct pkginfo *pkg,
223                             struct pkgbin *pkgbin, int signum,
224                             enum trig_options opts)
225 {
226 	ohshit(_("invalid or unknown syntax in trigger name '%.250s'"
227 	         " (in trigger interests for package '%.250s')"),
228 	       trig, pkgbin_name(pkg, pkgbin, pnaw_nonambig));
229 }
230 
231 static const struct trigkindinfo tki_unknown = {
232 	.activate_start = trk_unknown_activate_start,
233 	.activate_awaiter = trk_unknown_activate_awaiter,
234 	.activate_done = trk_unknown_activate_done,
235 	.interest_change = trk_unknown_interest_change,
236 };
237 
238 /*---------- Explicit triggers. ----------*/
239 
240 static FILE *trk_explicit_f;
241 static struct varbuf trk_explicit_fn;
242 static char *trk_explicit_trig;
243 
244 static void
trk_explicit_activate_done(void)245 trk_explicit_activate_done(void)
246 {
247 	if (trk_explicit_f) {
248 		fclose(trk_explicit_f);
249 		trk_explicit_f = NULL;
250 	}
251 }
252 
253 static void
trk_explicit_start(const char * trig)254 trk_explicit_start(const char *trig)
255 {
256 	trk_explicit_activate_done();
257 
258 	varbuf_reset(&trk_explicit_fn);
259 	varbuf_add_str(&trk_explicit_fn, triggersdir);
260 	varbuf_add_char(&trk_explicit_fn, '/');
261 	varbuf_add_str(&trk_explicit_fn, trig);
262 	varbuf_end_str(&trk_explicit_fn);
263 
264 	trk_explicit_f = fopen(trk_explicit_fn.buf, "r");
265 	if (!trk_explicit_f) {
266 		if (errno != ENOENT)
267 			ohshite(_("failed to open trigger interest list file '%.250s'"),
268 			        trk_explicit_fn.buf);
269 	}
270 }
271 
272 static int
trk_explicit_fgets(char * buf,size_t sz)273 trk_explicit_fgets(char *buf, size_t sz)
274 {
275 	return fgets_checked(buf, sz, trk_explicit_f, trk_explicit_fn.buf);
276 }
277 
278 static void
trk_explicit_activate_start(void)279 trk_explicit_activate_start(void)
280 {
281 	trk_explicit_start(trig_activating_name);
282 	trk_explicit_trig = trig_activating_name;
283 }
284 
285 static void
trk_explicit_activate_awaiter(struct pkginfo * aw)286 trk_explicit_activate_awaiter(struct pkginfo *aw)
287 {
288 	char buf[1024];
289 	struct pkginfo *pend;
290 
291 	if (!trk_explicit_f)
292 		return;
293 
294 	if (fseek(trk_explicit_f, 0, SEEK_SET))
295 		ohshite(_("failed to rewind trigger interest file '%.250s'"),
296 		        trk_explicit_fn.buf);
297 
298 	while (trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
299 		struct dpkg_error err;
300 		char *slash;
301 		bool noawait = false;
302 		slash = strchr(buf, '/');
303 		if (slash && strcmp("/noawait", slash) == 0) {
304 			noawait = true;
305 			*slash = '\0';
306 		}
307 		if (slash && strcmp("/await", slash) == 0) {
308 			noawait = false;
309 			*slash = '\0';
310 		}
311 
312 		pend = pkg_spec_parse_pkg(buf, &err);
313 		if (pend == NULL)
314 			ohshit(_("trigger interest file '%.250s' syntax error; "
315 			         "illegal package name '%.250s': %.250s"),
316 			       trk_explicit_fn.buf, buf, err.str);
317 
318 		trig_record_activation(pend, noawait ? NULL : aw,
319 		                       trk_explicit_trig);
320 	}
321 }
322 
323 static void
trk_explicit_interest_change(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,int signum,enum trig_options opts)324 trk_explicit_interest_change(const char *trig,  struct pkginfo *pkg,
325                              struct pkgbin *pkgbin, int signum,
326                              enum trig_options opts)
327 {
328 	char buf[1024];
329 	struct atomic_file *file;
330 	bool empty = true;
331 
332 	trk_explicit_start(trig);
333 	file = atomic_file_new(trk_explicit_fn.buf, 0);
334 	atomic_file_open(file);
335 
336 	while (trk_explicit_f && trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
337 		const char *pkgname = pkgbin_name(pkg, pkgbin, pnaw_nonambig);
338 		size_t len = strlen(pkgname);
339 
340 		if (strncmp(buf, pkgname, len) == 0 && len < sizeof(buf) &&
341 		    (buf[len] == '\0' || buf[len] == '/'))
342 			continue;
343 		fprintf(file->fp, "%s\n", buf);
344 		empty = false;
345 	}
346 	if (signum > 0) {
347 		fprintf(file->fp, "%s%s\n",
348 		        pkgbin_name(pkg, pkgbin, pnaw_nonambig),
349 		        (opts == TRIG_NOAWAIT) ? "/noawait" : "");
350 		empty = false;
351 	}
352 
353 	if (!empty)
354 		atomic_file_sync(file);
355 
356 	atomic_file_close(file);
357 
358 	if (empty)
359 		atomic_file_remove(file);
360 	else
361 		atomic_file_commit(file);
362 
363 	atomic_file_free(file);
364 
365 	dir_sync_path(triggersdir);
366 }
367 
368 static const struct trigkindinfo tki_explicit = {
369 	.activate_start = trk_explicit_activate_start,
370 	.activate_awaiter = trk_explicit_activate_awaiter,
371 	.activate_done = trk_explicit_activate_done,
372 	.interest_change = trk_explicit_interest_change,
373 };
374 
375 /*---------- File triggers. ----------*/
376 
377 static struct {
378 	struct trigfileint *head, *tail;
379 } filetriggers;
380 
381 /*
382  * Values:
383  *  -1: Not read.
384  *   0: Not edited.
385  *   1: Edited
386  */
387 static int filetriggers_edited = -1;
388 
389 /*
390  * Called by various people with signum -1 and +1 to mean remove and add
391  * and also by trig_file_interests_ensure() with signum +2 meaning add
392  * but die if already present.
393  */
394 static void
trk_file_interest_change(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,int signum,enum trig_options opts)395 trk_file_interest_change(const char *trig, struct pkginfo *pkg,
396                          struct pkgbin *pkgbin, int signum,
397                          enum trig_options opts)
398 {
399 	struct fsys_namenode *fnn;
400 	struct trigfileint **search, *tfi;
401 
402 	fnn = trigh.namenode_find(trig, signum <= 0);
403 	if (!fnn) {
404 		if (signum >= 0)
405 			internerr("lost filename node '%s' for package %s "
406 			          "triggered to add", trig,
407 			          pkgbin_name(pkg, pkgbin, pnaw_always));
408 		return;
409 	}
410 
411 	for (search = trigh.namenode_interested(fnn);
412 	     (tfi = *search);
413 	     search = &tfi->samefile_next)
414 		if (tfi->pkg == pkg)
415 			goto found;
416 
417 	/* Not found. */
418 	if (signum < 0)
419 		return;
420 
421 	tfi = nfmalloc(sizeof(*tfi));
422 	tfi->pkg = pkg;
423 	tfi->pkgbin = pkgbin;
424 	tfi->fnn = fnn;
425 	tfi->options = opts;
426 	tfi->samefile_next = *trigh.namenode_interested(fnn);
427 	*trigh.namenode_interested(fnn) = tfi;
428 
429 	LIST_LINK_TAIL_PART(filetriggers, tfi, inoverall);
430 	goto edited;
431 
432 found:
433 	tfi->options = opts;
434 	if (signum > 1)
435 		ohshit(_("duplicate file trigger interest for filename '%.250s' "
436 		         "and package '%.250s'"), trig,
437 		       pkgbin_name(pkg, pkgbin, pnaw_nonambig));
438 	if (signum > 0)
439 		return;
440 
441 	/* Remove it: */
442 	*search = tfi->samefile_next;
443 	LIST_UNLINK_PART(filetriggers, tfi, inoverall);
444 edited:
445 	filetriggers_edited = 1;
446 }
447 
448 static void
trig_file_interests_remove(void)449 trig_file_interests_remove(void)
450 {
451 	if (unlink(triggersfilefile) && errno != ENOENT)
452 		ohshite(_("cannot remove '%.250s'"), triggersfilefile);
453 }
454 
455 static void
trig_file_interests_update(void)456 trig_file_interests_update(void)
457 {
458 	struct trigfileint *tfi;
459 	struct atomic_file *file;
460 
461 	file = atomic_file_new(triggersfilefile, 0);
462 	atomic_file_open(file);
463 
464 	for (tfi = filetriggers.head; tfi; tfi = tfi->inoverall.next)
465 		fprintf(file->fp, "%s %s%s\n", trigh.namenode_name(tfi->fnn),
466 		        pkgbin_name(tfi->pkg, tfi->pkgbin, pnaw_nonambig),
467 		        (tfi->options == TRIG_NOAWAIT) ? "/noawait" : "");
468 
469 	atomic_file_sync(file);
470 	atomic_file_close(file);
471 	atomic_file_commit(file);
472 	atomic_file_free(file);
473 }
474 
475 void
trig_file_interests_save(void)476 trig_file_interests_save(void)
477 {
478 	if (filetriggers_edited <= 0)
479 		return;
480 
481 	if (!filetriggers.head)
482 		trig_file_interests_remove();
483 	else
484 		trig_file_interests_update();
485 
486 	dir_sync_path(triggersdir);
487 
488 	filetriggers_edited = 0;
489 }
490 
491 void
trig_file_interests_ensure(void)492 trig_file_interests_ensure(void)
493 {
494 	FILE *f;
495 	char linebuf[1024], *space;
496 	struct pkginfo *pkg;
497 	struct pkgbin *pkgbin;
498 
499 	if (filetriggers_edited >= 0)
500 		return;
501 
502 	f = fopen(triggersfilefile, "r");
503 	if (!f) {
504 		if (errno == ENOENT)
505 			goto ok;
506 		ohshite(_("unable to read file triggers file '%.250s'"),
507 		        triggersfilefile);
508 	}
509 
510 	push_cleanup(cu_closestream, ~0, 1, f);
511 	while (fgets_checked(linebuf, sizeof(linebuf), f, triggersfilefile) >= 0) {
512 		struct dpkg_error err;
513 		char *slash;
514 		enum trig_options trig_opts = TRIG_AWAIT;
515 		space = strchr(linebuf, ' ');
516 		if (!space || linebuf[0] != '/')
517 			ohshit(_("syntax error in file triggers file '%.250s'"),
518 			       triggersfilefile);
519 		*space++ = '\0';
520 
521 		slash = strchr(space, '/');
522 		if (slash && strcmp("/noawait", slash) == 0) {
523 			trig_opts = TRIG_NOAWAIT;
524 			*slash = '\0';
525 		}
526 		if (slash && strcmp("/await", slash) == 0) {
527 			trig_opts = TRIG_AWAIT;
528 			*slash = '\0';
529 		}
530 
531 		pkg = pkg_spec_parse_pkg(space, &err);
532 		if (pkg == NULL)
533 			ohshit(_("file triggers record mentions illegal "
534 			         "package name '%.250s' (for interest in file "
535 			         "'%.250s'): %.250s"), space, linebuf, err.str);
536 		pkgbin = &pkg->installed;
537 
538 		trk_file_interest_change(linebuf, pkg, pkgbin, +2, trig_opts);
539 	}
540 	pop_cleanup(ehflag_normaltidy);
541 ok:
542 	filetriggers_edited = 0;
543 }
544 
545 void
trig_file_activate_byname(const char * trig,struct pkginfo * aw)546 trig_file_activate_byname(const char *trig, struct pkginfo *aw)
547 {
548 	struct fsys_namenode *fnn = trigh.namenode_find(trig, 1);
549 
550 	if (fnn)
551 		trig_file_activate(fnn, aw);
552 }
553 
554 void
trig_file_activate(struct fsys_namenode * trig,struct pkginfo * aw)555 trig_file_activate(struct fsys_namenode *trig, struct pkginfo *aw)
556 {
557 	struct trigfileint *tfi;
558 
559 	for (tfi = *trigh.namenode_interested(trig); tfi;
560 	     tfi = tfi->samefile_next)
561 		trig_record_activation(tfi->pkg, (tfi->options == TRIG_NOAWAIT) ?
562 		                       NULL : aw, trigh.namenode_name(trig));
563 }
564 
565 static void
trig_file_activate_parents(const char * trig,struct pkginfo * aw)566 trig_file_activate_parents(const char *trig, struct pkginfo *aw)
567 {
568 	char *path, *slash;
569 
570 	/* Traverse the whole pathname to activate all of its components. */
571 	path = m_strdup(trig);
572 
573 	while ((slash = strrchr(path, '/'))) {
574 		*slash = '\0';
575 		trig_file_activate_byname(path, aw);
576 	}
577 
578 	free(path);
579 }
580 
581 void
trig_path_activate(struct fsys_namenode * trig,struct pkginfo * aw)582 trig_path_activate(struct fsys_namenode *trig, struct pkginfo *aw)
583 {
584 	trig_file_activate(trig, aw);
585 	trig_file_activate_parents(trigh.namenode_name(trig), aw);
586 }
587 
588 static void
trig_path_activate_byname(const char * trig,struct pkginfo * aw)589 trig_path_activate_byname(const char *trig, struct pkginfo *aw)
590 {
591 	struct fsys_namenode *fnn = trigh.namenode_find(trig, 1);
592 
593 	if (fnn)
594 		trig_file_activate(fnn, aw);
595 
596 	trig_file_activate_parents(trig, aw);
597 }
598 
599 static const char *trk_file_trig;
600 
601 static void
trk_file_activate_start(void)602 trk_file_activate_start(void)
603 {
604 	trk_file_trig = trig_activating_name;
605 }
606 
607 static void
trk_file_activate_awaiter(struct pkginfo * aw)608 trk_file_activate_awaiter(struct pkginfo *aw)
609 {
610 	trig_path_activate_byname(trk_file_trig, aw);
611 }
612 
613 static void
trk_file_activate_done(void)614 trk_file_activate_done(void)
615 {
616 }
617 
618 static const struct trigkindinfo tki_file = {
619 	.activate_start = trk_file_activate_start,
620 	.activate_awaiter = trk_file_activate_awaiter,
621 	.activate_done = trk_file_activate_done,
622 	.interest_change = trk_file_interest_change,
623 };
624 
625 /*---------- Trigger control info file. ----------*/
626 
627 static void
trig_cicb_interest_change(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,int signum,enum trig_options opts)628 trig_cicb_interest_change(const char *trig, struct pkginfo *pkg,
629                           struct pkgbin *pkgbin, int signum,
630                           enum trig_options opts)
631 {
632 	const struct trigkindinfo *tki = trig_classify_byname(trig);
633 
634 	if (filetriggers_edited < 0)
635 		internerr("trigger control file for package %s not read",
636 		          pkgbin_name(pkg, pkgbin, pnaw_always));
637 
638 	tki->interest_change(trig, pkg, pkgbin, signum, opts);
639 }
640 
641 void
trig_cicb_interest_delete(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,enum trig_options opts)642 trig_cicb_interest_delete(const char *trig, struct pkginfo *pkg,
643                           struct pkgbin *pkgbin, enum trig_options opts)
644 {
645 	trig_cicb_interest_change(trig, pkg, pkgbin, -1, opts);
646 }
647 
648 void
trig_cicb_interest_add(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,enum trig_options opts)649 trig_cicb_interest_add(const char *trig, struct pkginfo *pkg,
650                        struct pkgbin *pkgbin, enum trig_options opts)
651 {
652 	trig_cicb_interest_change(trig, pkg, pkgbin, +1, opts);
653 }
654 
655 void
trig_cicb_statuschange_activate(const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,enum trig_options opts)656 trig_cicb_statuschange_activate(const char *trig, struct pkginfo *pkg,
657                                 struct pkgbin *pkgbin, enum trig_options opts)
658 {
659 	struct pkginfo *aw = pkg;
660 
661 	trig_activate_start(trig);
662 	dtki->activate_awaiter((opts == TRIG_NOAWAIT) ? NULL : aw);
663 	dtki->activate_done();
664 }
665 
666 static void
parse_ci_call(const char * file,const char * cmd,trig_parse_cicb * cb,const char * trig,struct pkginfo * pkg,struct pkgbin * pkgbin,enum trig_options opts)667 parse_ci_call(const char *file, const char *cmd, trig_parse_cicb *cb,
668               const char *trig, struct pkginfo *pkg, struct pkgbin *pkgbin,
669               enum trig_options opts)
670 {
671 	const char *emsg;
672 
673 	emsg = trig_name_is_illegal(trig);
674 	if (emsg)
675 		ohshit(_("triggers ci file '%.250s' contains illegal trigger "
676 		         "syntax in trigger name '%.250s': %.250s"),
677 		       file, trig, emsg);
678 	if (cb)
679 		cb(trig, pkg, pkgbin, opts);
680 }
681 
682 void
trig_parse_ci(const char * file,trig_parse_cicb * interest,trig_parse_cicb * activate,struct pkginfo * pkg,struct pkgbin * pkgbin)683 trig_parse_ci(const char *file, trig_parse_cicb *interest,
684               trig_parse_cicb *activate, struct pkginfo *pkg,
685               struct pkgbin *pkgbin)
686 {
687 	FILE *f;
688 	char linebuf[MAXTRIGDIRECTIVE], *cmd, *spc, *eol;
689 	int l;
690 
691 	f = fopen(file, "r");
692 	if (!f) {
693 		if (errno == ENOENT)
694 			return; /* No file is just like an empty one. */
695 		ohshite(_("unable to open triggers ci file '%.250s'"), file);
696 	}
697 	push_cleanup(cu_closestream, ~0, 1, f);
698 
699 	while ((l = fgets_checked(linebuf, sizeof(linebuf), f, file)) >= 0) {
700 		for (cmd = linebuf; c_iswhite(*cmd); cmd++) ;
701 		if (*cmd == '#')
702 			continue;
703 		for (eol = linebuf + l; eol > cmd && c_iswhite(eol[-1]); eol--) ;
704 		if (eol == cmd)
705 			continue;
706 		*eol = '\0';
707 
708 		for (spc = cmd; *spc && !c_iswhite(*spc); spc++) ;
709 		if (!*spc)
710 			ohshit(_("triggers ci file contains unknown directive syntax"));
711 		*spc++ = '\0';
712 		while (c_iswhite(*spc))
713 			spc++;
714 		if (strcmp(cmd, "interest") == 0 ||
715 		    strcmp(cmd, "interest-await") == 0) {
716 			parse_ci_call(file, cmd, interest, spc, pkg, pkgbin, TRIG_AWAIT);
717 		} else if (strcmp(cmd, "interest-noawait") == 0) {
718 			parse_ci_call(file, cmd, interest, spc, pkg, pkgbin, TRIG_NOAWAIT);
719 		} else if (strcmp(cmd, "activate") == 0 ||
720 		           strcmp(cmd, "activate-await") == 0) {
721 			parse_ci_call(file, cmd, activate, spc, pkg, pkgbin, TRIG_AWAIT);
722 		} else if (strcmp(cmd, "activate-noawait") == 0) {
723 			parse_ci_call(file, cmd, activate, spc, pkg, pkgbin, TRIG_NOAWAIT);
724 		} else {
725 			ohshit(_("triggers ci file contains unknown directive '%.250s'"),
726 			       cmd);
727 		}
728 	}
729 	pop_cleanup(ehflag_normaltidy); /* fclose() */
730 }
731 
732 /*---------- Unincorp file incorporation. ----------*/
733 
734 static void
tdm_incorp_trig_begin(const char * trig)735 tdm_incorp_trig_begin(const char *trig)
736 {
737 	trig_activate_start(trig);
738 }
739 
740 static void
tdm_incorp_package(const char * awname)741 tdm_incorp_package(const char *awname)
742 {
743 	struct pkginfo *aw;
744 
745 	if (strcmp(awname, "-") == 0)
746 		aw = NULL;
747 	else
748 		aw = pkg_spec_parse_pkg(awname, NULL);
749 
750 	dtki->activate_awaiter(aw);
751 }
752 
753 static void
tdm_incorp_trig_end(void)754 tdm_incorp_trig_end(void)
755 {
756 	dtki->activate_done();
757 }
758 
759 static const struct trigdefmeths tdm_incorp = {
760 	.trig_begin = tdm_incorp_trig_begin,
761 	.package = tdm_incorp_package,
762 	.trig_end = tdm_incorp_trig_end
763 };
764 
765 void
trig_incorporate(enum modstatdb_rw cstatus)766 trig_incorporate(enum modstatdb_rw cstatus)
767 {
768 	enum trigdef_update_status ur;
769 	enum trigdef_update_flags tduf;
770 
771 	free(triggersdir);
772 	triggersdir = dpkg_db_get_path(TRIGGERSDIR);
773 
774 	free(triggersfilefile);
775 	triggersfilefile = trig_get_filename(triggersdir, TRIGGERSFILEFILE);
776 
777 	trigdef_set_methods(&tdm_incorp);
778 	trig_file_interests_ensure();
779 
780 	tduf = TDUF_NO_LOCK_OK;
781 	if (cstatus >= msdbrw_write) {
782 		tduf |= TDUF_WRITE;
783 		if (trigh.transitional_activate)
784 			tduf |= TDUF_WRITE_IF_ENOENT;
785 	}
786 
787 	ur = trigdef_update_start(tduf);
788 	if (ur == TDUS_ERROR_NO_DIR && cstatus >= msdbrw_write) {
789 		if (mkdir(triggersdir, 0755)) {
790 			if (errno != EEXIST)
791 				ohshite(_("unable to create triggers state"
792 				          " directory '%.250s'"), triggersdir);
793 		} else if (chown(triggersdir, 0, 0)) {
794 			ohshite(_("unable to set ownership of triggers state"
795 			          " directory '%.250s'"), triggersdir);
796 		}
797 		ur = trigdef_update_start(tduf);
798 	}
799 	switch (ur) {
800 	case TDUS_ERROR_EMPTY_DEFERRED:
801 		return;
802 	case TDUS_ERROR_NO_DIR:
803 	case TDUS_ERROR_NO_DEFERRED:
804 		if (!trigh.transitional_activate)
805 			return;
806 	/* Fall through. */
807 	case TDUS_NO_DEFERRED:
808 		trigh.transitional_activate(cstatus);
809 		break;
810 	case TDUS_OK:
811 		/* Read and incorporate triggers. */
812 		trigdef_parse();
813 		break;
814 	default:
815 		internerr("unknown trigdef_update_start return value '%d'", ur);
816 	}
817 
818 	/* Right, that's it. New (empty) Unincorp can be installed. */
819 	trigdef_process_done();
820 }
821 
822 /*---------- Default hooks. ----------*/
823 
824 TRIGHOOKS_DEFINE_NAMENODE_ACCESSORS
825 
826 static struct trig_hooks trigh = {
827 	.enqueue_deferred = NULL,
828 	.transitional_activate = NULL,
829 	.namenode_find = th_nn_find,
830 	.namenode_interested = th_nn_interested,
831 	.namenode_name = th_nn_name,
832 };
833 
834 void
trig_override_hooks(const struct trig_hooks * hooks)835 trig_override_hooks(const struct trig_hooks *hooks)
836 {
837 	trigh = *hooks;
838 }
839