po: Update German man pages translation
[dpkg.git] / lib / dpkg / triglib.c
blob28fb74518e793b491b77816d9da78bb86cea9c4b
1 /*
2 * libdpkg - Debian packaging suite library routines
3 * triglib.c - trigger handling
5 * Copyright © 2007 Canonical Ltd
6 * Written by Ian Jackson <ijackson@chiark.greenend.org.uk>
7 * Copyright © 2008-2015 Guillem Jover <guillem@debian.org>
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.
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.
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/>.
23 #include <config.h>
24 #include <compat.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <unistd.h>
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>
44 /*========== Recording triggers. ==========*/
46 static char *triggersdir, *triggersfilefile;
48 static char *
49 trig_get_filename(const char *dir, const char *filename)
51 return str_fmt("%s/%s", dir, filename);
54 static struct trig_hooks trigh;
56 /*---------- Noting trigger activation in memory. ----------*/
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
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.
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.)
77 * aw might be NULL.
78 * trig is not copied!
80 static void
81 trig_record_activation(struct pkginfo *pend, struct pkginfo *aw, const char *trig)
83 if (pend->status < PKG_STAT_TRIGGERSAWAITED)
84 return; /* Not interested then. */
86 if (trig_note_pend(pend, trig))
87 modstatdb_note_ifwrite(pend);
89 if (trigh.enqueue_deferred)
90 trigh.enqueue_deferred(pend);
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);
100 void
101 trig_clear_awaiters(struct pkginfo *notpend)
103 struct trigaw *ta;
104 struct pkginfo *aw;
106 if (notpend->trigpend_head)
107 internerr("package %s has pending triggers",
108 pkg_name(notpend, pnaw_always));
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);
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.
133 * XXX: Possibly get rid of some of the checks done somewhere else for
134 * this condition at run-time.
136 void
137 trig_fixup_awaiters(enum modstatdb_rw cstatus)
139 if (cstatus < msdbrw_write)
140 return;
142 trig_awaited_pend_foreach(trig_clear_awaiters);
143 trig_awaited_pend_free();
146 /*---------- Generalized handling of trigger kinds. ----------*/
148 struct trigkindinfo {
149 /* Only for trig_activate_start. */
150 void (*activate_start)(void);
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);
160 static const struct trigkindinfo tki_explicit, tki_file, tki_unknown;
161 static const struct trigkindinfo *dtki;
163 /* As passed into activate_start. */
164 static char *trig_activating_name;
166 static const struct trigkindinfo *
167 trig_classify_byname(const char *name)
169 if (name[0] == '/') {
170 const char *slash;
172 slash = name;
173 while (slash) {
174 if (slash[1] == '\0' || slash[1] == '/')
175 goto invalid;
177 slash = strchr(slash + 2, '/');
179 return &tki_file;
182 if (!pkg_name_is_illegal(name) && !strchr(name, '_'))
183 return &tki_explicit;
185 invalid:
186 return &tki_unknown;
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();
196 static void
197 trig_activate_start(const char *name)
199 dtki = trig_classify_byname(name);
200 trig_activating_name = nfstrsave(name);
201 dtki->activate_start();
204 /*---------- Unknown trigger kinds. ----------*/
206 static void
207 trk_unknown_activate_start(void)
211 static void
212 trk_unknown_activate_awaiter(struct pkginfo *aw)
216 static void
217 trk_unknown_activate_done(void)
221 static void DPKG_ATTR_NORET
222 trk_unknown_interest_change(const char *trig, struct pkginfo *pkg,
223 struct pkgbin *pkgbin, int signum,
224 enum trig_options opts)
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));
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,
238 /*---------- Explicit triggers. ----------*/
240 static FILE *trk_explicit_f;
241 static struct varbuf trk_explicit_fn;
242 static char *trk_explicit_trig;
244 static void
245 trk_explicit_activate_done(void)
247 if (trk_explicit_f) {
248 fclose(trk_explicit_f);
249 trk_explicit_f = NULL;
253 static void
254 trk_explicit_start(const char *trig)
256 trk_explicit_activate_done();
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);
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);
272 static int
273 trk_explicit_fgets(char *buf, size_t sz)
275 return fgets_checked(buf, sz, trk_explicit_f, trk_explicit_fn.buf);
278 static void
279 trk_explicit_activate_start(void)
281 trk_explicit_start(trig_activating_name);
282 trk_explicit_trig = trig_activating_name;
285 static void
286 trk_explicit_activate_awaiter(struct pkginfo *aw)
288 char buf[1024];
289 struct pkginfo *pend;
291 if (!trk_explicit_f)
292 return;
294 if (fseek(trk_explicit_f, 0, SEEK_SET))
295 ohshite(_("failed to rewind trigger interest file '%.250s'"),
296 trk_explicit_fn.buf);
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';
307 if (slash && strcmp("/await", slash) == 0) {
308 noawait = false;
309 *slash = '\0';
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);
318 trig_record_activation(pend, noawait ? NULL : aw,
319 trk_explicit_trig);
323 static void
324 trk_explicit_interest_change(const char *trig, struct pkginfo *pkg,
325 struct pkgbin *pkgbin, int signum,
326 enum trig_options opts)
328 char buf[1024];
329 struct atomic_file *file;
330 bool empty = true;
332 trk_explicit_start(trig);
333 file = atomic_file_new(trk_explicit_fn.buf, 0);
334 atomic_file_open(file);
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);
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;
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;
353 if (!empty)
354 atomic_file_sync(file);
356 atomic_file_close(file);
358 if (empty)
359 atomic_file_remove(file);
360 else
361 atomic_file_commit(file);
363 atomic_file_free(file);
365 dir_sync_path(triggersdir);
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,
375 /*---------- File triggers. ----------*/
377 static struct {
378 struct trigfileint *head, *tail;
379 } filetriggers;
382 * Values:
383 * -1: Not read.
384 * 0: Not edited.
385 * 1: Edited
387 static int filetriggers_edited = -1;
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.
394 static void
395 trk_file_interest_change(const char *trig, struct pkginfo *pkg,
396 struct pkgbin *pkgbin, int signum,
397 enum trig_options opts)
399 struct fsys_namenode *fnn;
400 struct trigfileint **search, *tfi;
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;
411 for (search = trigh.namenode_interested(fnn);
412 (tfi = *search);
413 search = &tfi->samefile_next)
414 if (tfi->pkg == pkg)
415 goto found;
417 /* Not found. */
418 if (signum < 0)
419 return;
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;
429 LIST_LINK_TAIL_PART(filetriggers, tfi, inoverall);
430 goto edited;
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;
441 /* Remove it: */
442 *search = tfi->samefile_next;
443 LIST_UNLINK_PART(filetriggers, tfi, inoverall);
444 edited:
445 filetriggers_edited = 1;
448 static void
449 trig_file_interests_remove(void)
451 if (unlink(triggersfilefile) && errno != ENOENT)
452 ohshite(_("cannot remove '%.250s'"), triggersfilefile);
455 static void
456 trig_file_interests_update(void)
458 struct trigfileint *tfi;
459 struct atomic_file *file;
461 file = atomic_file_new(triggersfilefile, 0);
462 atomic_file_open(file);
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" : "");
469 atomic_file_sync(file);
470 atomic_file_close(file);
471 atomic_file_commit(file);
472 atomic_file_free(file);
475 void
476 trig_file_interests_save(void)
478 if (filetriggers_edited <= 0)
479 return;
481 if (!filetriggers.head)
482 trig_file_interests_remove();
483 else
484 trig_file_interests_update();
486 dir_sync_path(triggersdir);
488 filetriggers_edited = 0;
491 void
492 trig_file_interests_ensure(void)
494 FILE *f;
495 char linebuf[1024], *space;
496 struct pkginfo *pkg;
497 struct pkgbin *pkgbin;
499 if (filetriggers_edited >= 0)
500 return;
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);
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';
521 slash = strchr(space, '/');
522 if (slash && strcmp("/noawait", slash) == 0) {
523 trig_opts = TRIG_NOAWAIT;
524 *slash = '\0';
526 if (slash && strcmp("/await", slash) == 0) {
527 trig_opts = TRIG_AWAIT;
528 *slash = '\0';
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;
538 trk_file_interest_change(linebuf, pkg, pkgbin, +2, trig_opts);
540 pop_cleanup(ehflag_normaltidy);
542 filetriggers_edited = 0;
545 void
546 trig_file_activate_byname(const char *trig, struct pkginfo *aw)
548 struct fsys_namenode *fnn = trigh.namenode_find(trig, 1);
550 if (fnn)
551 trig_file_activate(fnn, aw);
554 void
555 trig_file_activate(struct fsys_namenode *trig, struct pkginfo *aw)
557 struct trigfileint *tfi;
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));
565 static void
566 trig_file_activate_parents(const char *trig, struct pkginfo *aw)
568 char *path, *slash;
570 /* Traverse the whole pathname to activate all of its components. */
571 path = m_strdup(trig);
573 while ((slash = strrchr(path, '/'))) {
574 *slash = '\0';
575 trig_file_activate_byname(path, aw);
578 free(path);
581 void
582 trig_path_activate(struct fsys_namenode *trig, struct pkginfo *aw)
584 trig_file_activate(trig, aw);
585 trig_file_activate_parents(trigh.namenode_name(trig), aw);
588 static void
589 trig_path_activate_byname(const char *trig, struct pkginfo *aw)
591 struct fsys_namenode *fnn = trigh.namenode_find(trig, 1);
593 if (fnn)
594 trig_file_activate(fnn, aw);
596 trig_file_activate_parents(trig, aw);
599 static const char *trk_file_trig;
601 static void
602 trk_file_activate_start(void)
604 trk_file_trig = trig_activating_name;
607 static void
608 trk_file_activate_awaiter(struct pkginfo *aw)
610 trig_path_activate_byname(trk_file_trig, aw);
613 static void
614 trk_file_activate_done(void)
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,
625 /*---------- Trigger control info file. ----------*/
627 static void
628 trig_cicb_interest_change(const char *trig, struct pkginfo *pkg,
629 struct pkgbin *pkgbin, int signum,
630 enum trig_options opts)
632 const struct trigkindinfo *tki = trig_classify_byname(trig);
634 if (filetriggers_edited < 0)
635 internerr("trigger control file for package %s not read",
636 pkgbin_name(pkg, pkgbin, pnaw_always));
638 tki->interest_change(trig, pkg, pkgbin, signum, opts);
641 void
642 trig_cicb_interest_delete(const char *trig, struct pkginfo *pkg,
643 struct pkgbin *pkgbin, enum trig_options opts)
645 trig_cicb_interest_change(trig, pkg, pkgbin, -1, opts);
648 void
649 trig_cicb_interest_add(const char *trig, struct pkginfo *pkg,
650 struct pkgbin *pkgbin, enum trig_options opts)
652 trig_cicb_interest_change(trig, pkg, pkgbin, +1, opts);
655 void
656 trig_cicb_statuschange_activate(const char *trig, struct pkginfo *pkg,
657 struct pkgbin *pkgbin, enum trig_options opts)
659 struct pkginfo *aw = pkg;
661 trig_activate_start(trig);
662 dtki->activate_awaiter((opts == TRIG_NOAWAIT) ? NULL : aw);
663 dtki->activate_done();
666 static void
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)
671 const char *emsg;
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);
682 void
683 trig_parse_ci(const char *file, trig_parse_cicb *interest,
684 trig_parse_cicb *activate, struct pkginfo *pkg,
685 struct pkgbin *pkgbin)
687 FILE *f;
688 char linebuf[MAXTRIGDIRECTIVE], *cmd, *spc, *eol;
689 int l;
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);
697 push_cleanup(cu_closestream, ~0, 1, f);
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';
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);
729 pop_cleanup(ehflag_normaltidy); /* fclose() */
732 /*---------- Unincorp file incorporation. ----------*/
734 static void
735 tdm_incorp_trig_begin(const char *trig)
737 trig_activate_start(trig);
740 static void
741 tdm_incorp_package(const char *awname)
743 struct pkginfo *aw;
745 if (strcmp(awname, "-") == 0)
746 aw = NULL;
747 else
748 aw = pkg_spec_parse_pkg(awname, NULL);
750 dtki->activate_awaiter(aw);
753 static void
754 tdm_incorp_trig_end(void)
756 dtki->activate_done();
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
765 void
766 trig_incorporate(enum modstatdb_rw cstatus)
768 enum trigdef_update_status ur;
769 enum trigdef_update_flags tduf;
771 free(triggersdir);
772 triggersdir = dpkg_db_get_path(TRIGGERSDIR);
774 free(triggersfilefile);
775 triggersfilefile = trig_get_filename(triggersdir, TRIGGERSFILEFILE);
777 trigdef_set_methods(&tdm_incorp);
778 trig_file_interests_ensure();
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;
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);
794 ur = trigdef_update_start(tduf);
796 switch (ur) {
797 case TDUS_ERROR_EMPTY_DEFERRED:
798 return;
799 case TDUS_ERROR_NO_DIR:
800 case TDUS_ERROR_NO_DEFERRED:
801 if (!trigh.transitional_activate)
802 return;
803 /* Fall through. */
804 case TDUS_NO_DEFERRED:
805 trigh.transitional_activate(cstatus);
806 break;
807 case TDUS_OK:
808 /* Read and incorporate triggers. */
809 trigdef_parse();
810 break;
811 default:
812 internerr("unknown trigdef_update_start return value '%d'", ur);
815 /* Right, that's it. New (empty) Unincorp can be installed. */
816 trigdef_process_done();
819 /*---------- Default hooks. ----------*/
821 TRIGHOOKS_DEFINE_NAMENODE_ACCESSORS
823 static struct trig_hooks trigh = {
824 .enqueue_deferred = NULL,
825 .transitional_activate = NULL,
826 .namenode_find = th_nn_find,
827 .namenode_interested = th_nn_interested,
828 .namenode_name = th_nn_name,
831 void
832 trig_override_hooks(const struct trig_hooks *hooks)
834 trigh = *hooks;