triglib.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * triglib.c - trigger handling
  4. *
  5. * Copyright (C) 2007 Canonical Ltd
  6. * Written by Ian Jackson <ian@chiark.greenend.org.uk>
  7. *
  8. * This is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2,
  11. * or (at your option) any later version.
  12. *
  13. * This is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public
  19. * License along with dpkg; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. #include <config.h>
  23. #include <assert.h>
  24. #include <unistd.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <dpkg.h>
  29. #include <dpkg-db.h>
  30. #include <dlist.h>
  31. const char *
  32. illegal_triggername(const char *p)
  33. {
  34. int c;
  35. if (!*p)
  36. return _("empty trigger names are not permitted");
  37. while ((c = *p++)) {
  38. if (c <= ' ' || c >= 0177)
  39. return _("trigger name contains invalid character");
  40. }
  41. return NULL;
  42. }
  43. /*========== recording triggers ==========*/
  44. /*---------- noting trigger activation in memory ----------*/
  45. /* Called via trig_*activate* et al from:
  46. * - trig_incorporate: reading of Unincorp (explicit trigger activations)
  47. * - various places: processing start (`activate' in triggers ci file)
  48. * - namenodetouse: file triggers during unpack / remove
  49. * - deferred_configure: file triggers during config file processing
  50. *
  51. * Not called from trig_transitional_activation; that runs
  52. * trig_note_pend directly which means that (a) awaiters are not
  53. * recorded (how would we know?) and (b) we don't enqueue them for
  54. * deferred processing in this run.
  55. *
  56. * We add the trigger to Triggers-Pending first. This makes it
  57. * harder to get into the state where Triggers-Awaited for aw lists
  58. * pend but Triggers-Pending for pend is empty. (See also the
  59. * comment in deppossi_ok_found regarding this situation.)
  60. */
  61. /* aw might be NULL, and trig is not copied! */
  62. static void
  63. trig_record_activation(struct pkginfo *pend, struct pkginfo *aw, char *trig)
  64. {
  65. if (pend->status < stat_triggersawaited)
  66. /* Not interested then. */
  67. return;
  68. if (trig_note_pend(pend, trig))
  69. modstatdb_note_ifwrite(pend);
  70. if (trigh.enqueue_deferred)
  71. trigh.enqueue_deferred(pend);
  72. if (aw && pend->status > stat_configfiles)
  73. if (trig_note_aw(pend, aw)) {
  74. if (aw->status > stat_triggersawaited)
  75. aw->status = stat_triggersawaited;
  76. modstatdb_note_ifwrite(aw);
  77. }
  78. }
  79. /* NB that this is also called from fields.c where *pend is a temporary! */
  80. int
  81. trig_note_pend_core(struct pkginfo *pend, char *trig /*not copied!*/)
  82. {
  83. struct trigpend *tp;
  84. for (tp = pend->trigpend_head; tp; tp = tp->next)
  85. if (!strcmp(tp->name, trig))
  86. return 0;
  87. tp = nfmalloc(sizeof(*tp));
  88. tp->name = trig;
  89. tp->next = pend->trigpend_head;
  90. pend->trigpend_head = tp;
  91. return 1;
  92. }
  93. /* Returns: 1 for done, 0 for already noted. */
  94. int
  95. trig_note_pend(struct pkginfo *pend, char *trig /*not copied!*/)
  96. {
  97. if (!trig_note_pend_core(pend, trig))
  98. return 0;
  99. pend->status = pend->trigaw.head ? stat_triggersawaited :
  100. stat_triggerspending;
  101. return 1;
  102. }
  103. /* Returns: 1 for done, 0 for already noted. */
  104. /* NB that this is called also from fields.c where *aw is a temporary
  105. * but pend is from findpackage()! */
  106. int
  107. trig_note_aw(struct pkginfo *pend, struct pkginfo *aw)
  108. {
  109. struct trigaw *ta;
  110. /* We search through aw's list because that's probably shorter. */
  111. for (ta = aw->trigaw.head; ta; ta = ta->sameaw.next)
  112. if (ta->pend == pend)
  113. return 0;
  114. ta = nfmalloc(sizeof(*ta));
  115. ta->aw = aw;
  116. ta->pend = pend;
  117. ta->nextsamepend = pend->othertrigaw_head;
  118. pend->othertrigaw_head = ta;
  119. LIST_LINK_TAIL_PART(aw->trigaw, ta, sameaw.);
  120. return 1;
  121. }
  122. void
  123. trig_clear_awaiters(struct pkginfo *notpend)
  124. {
  125. struct trigaw *ta;
  126. struct pkginfo *aw;
  127. assert(!notpend->trigpend_head);
  128. ta = notpend->othertrigaw_head;
  129. notpend->othertrigaw_head = NULL;
  130. for (; ta; ta = ta->nextsamepend) {
  131. aw = ta->aw;
  132. if (!aw)
  133. continue;
  134. LIST_UNLINK_PART(aw->trigaw, ta, sameaw.);
  135. if (!aw->trigaw.head && aw->status == stat_triggersawaited) {
  136. aw->status = aw->trigpend_head ? stat_triggerspending :
  137. stat_installed;
  138. modstatdb_note(aw);
  139. }
  140. }
  141. }
  142. /*---------- generalised handling of trigger kinds ----------*/
  143. static const struct trigkindinfo tki_explicit, tki_file, tki_unknown;
  144. struct trigkindinfo {
  145. /* Only for trig_activate_start. */
  146. void (*activate_start)(void);
  147. /* Rest are for everyone: */
  148. void (*activate_awaiter)(struct pkginfo *pkg /* may be NULL */);
  149. void (*activate_done)(void);
  150. void (*interest_change)(const char *name, struct pkginfo *pkg, int signum);
  151. };
  152. #define TKI_DEFINE(kindname) \
  153. static const struct trigkindinfo tki_##kindname= { \
  154. trk_##kindname##_activate_start, \
  155. trk_##kindname##_activate_awaiter, \
  156. trk_##kindname##_activate_done, \
  157. trk_##kindname##_interest_change \
  158. };
  159. static const struct trigkindinfo *dtki;
  160. /* As passed into activate_start. */
  161. static const char *trig_activating_name;
  162. static const struct trigkindinfo *
  163. trig_classify_byname(const char *name)
  164. {
  165. if (name[0] == '/') {
  166. const char *slash;
  167. slash = name;
  168. while (slash) {
  169. if (slash[1] == 0 || slash[1] == '/')
  170. goto invalid;
  171. slash = strchr(slash + 2, '/');
  172. }
  173. return &tki_file;
  174. }
  175. if (!illegal_packagename(name, NULL) && !strchr(name, '_'))
  176. return &tki_explicit;
  177. invalid:
  178. return &tki_unknown;
  179. }
  180. /* Calling sequence is:
  181. * trig_activate_start(triggername)
  182. * dtki->activate_awaiter(awaiting_package) } zero or more times
  183. * dtki->activate_awaiter(0) } in any order
  184. * dtki->activate_done(0)
  185. */
  186. static void
  187. trig_activate_start(const char *name)
  188. {
  189. dtki = trig_classify_byname(name);
  190. trig_activating_name = name;
  191. dtki->activate_start();
  192. }
  193. /*---------- unknown trigger kinds ----------*/
  194. static void
  195. trk_unknown_activate_start(void)
  196. {
  197. }
  198. static void
  199. trk_unknown_activate_awaiter(struct pkginfo *aw)
  200. {
  201. }
  202. static void
  203. trk_unknown_activate_done(void)
  204. {
  205. }
  206. static void
  207. trk_unknown_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  208. {
  209. ohshit(_("invalid or unknown syntax in trigger name `%.250s'"
  210. " (in trigger interests for package `%.250s'"),
  211. trig, pkg->name);
  212. }
  213. TKI_DEFINE(unknown);
  214. /*---------- explicit triggers ----------*/
  215. static FILE *trk_explicit_f;
  216. static struct varbuf trk_explicit_fn;
  217. static char *trk_explicit_trig;
  218. static void
  219. trk_explicit_activate_done(void)
  220. {
  221. if (trk_explicit_f) {
  222. fclose(trk_explicit_f);
  223. trk_explicit_f = NULL;
  224. }
  225. }
  226. static void
  227. trk_explicit_start(const char *trig)
  228. {
  229. trk_explicit_activate_done();
  230. varbufreset(&trk_explicit_fn);
  231. varbufaddstr(&trk_explicit_fn, triggersdir);
  232. varbufaddstr(&trk_explicit_fn, trig);
  233. varbufaddc(&trk_explicit_fn, 0);
  234. trk_explicit_f = fopen(trk_explicit_fn.buf, "r");
  235. if (!trk_explicit_f) {
  236. if (errno != ENOENT)
  237. ohshite(_("failed to open trigger interest list file `%.250s'"),
  238. trk_explicit_fn.buf);
  239. }
  240. }
  241. static int
  242. trk_explicit_fgets(char *buf, size_t sz)
  243. {
  244. return fgets_checked(buf, sz, trk_explicit_f, trk_explicit_fn.buf);
  245. }
  246. static void
  247. trk_explicit_activate_start(void)
  248. {
  249. trk_explicit_start(trig_activating_name);
  250. trk_explicit_trig = nfstrsave(trig_activating_name);
  251. }
  252. static void
  253. trk_explicit_activate_awaiter(struct pkginfo *aw)
  254. {
  255. char buf[1024];
  256. const char *emsg;
  257. struct pkginfo *pend;
  258. if (!trk_explicit_f)
  259. return;
  260. if (fseek(trk_explicit_f, 0, SEEK_SET))
  261. ohshite(_("failed to rewind trigger interest file `%.250s'"),
  262. trk_explicit_fn.buf);
  263. while (trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
  264. if ((emsg = illegal_packagename(buf, NULL)))
  265. ohshit(_("trigger interest file `%.250s' syntax error; "
  266. "illegal package name `%.250s': %.250s"),
  267. trk_explicit_fn.buf, buf, emsg);
  268. pend = findpackage(buf);
  269. trig_record_activation(pend, aw, trk_explicit_trig);
  270. }
  271. }
  272. static void
  273. trk_explicit_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  274. {
  275. static struct varbuf newfn;
  276. char buf[1024];
  277. FILE *nf;
  278. trk_explicit_start(trig);
  279. varbufreset(&newfn);
  280. varbufprintf(&newfn, "%s/%s.new", triggersdir, trig);
  281. varbufaddc(&newfn, 0);
  282. nf = fopen(newfn.buf, "w");
  283. if (!nf)
  284. ohshite(_("unable to create new trigger interest file `%.250s'"),
  285. newfn.buf);
  286. push_cleanup(cu_closefile, ~ehflag_normaltidy, NULL, 0, 1, nf);
  287. while (trk_explicit_f && trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
  288. if (!strcmp(buf, pkg->name))
  289. continue;
  290. fprintf(nf, "%s\n", buf);
  291. }
  292. if (signum > 0)
  293. fprintf(nf, "%s\n", pkg->name);
  294. if (ferror(nf) || fclose(nf))
  295. ohshite(_("unable to write new trigger interest file `%.250s'"),
  296. newfn.buf);
  297. pop_cleanup(ehflag_normaltidy);
  298. if (rename(newfn.buf, trk_explicit_fn.buf))
  299. ohshite(_("unable to install new trigger interest file `%.250s'"),
  300. trk_explicit_fn.buf);
  301. }
  302. TKI_DEFINE(explicit);
  303. /*---------- file triggers ----------*/
  304. static struct {
  305. struct trigfileint *head, *tail;
  306. } filetriggers;
  307. /*
  308. * Values:
  309. * -1: not read,
  310. * 0: not edited
  311. * 1: edited
  312. */
  313. static int filetriggers_edited = -1;
  314. /* Called by various people with signum -1 and +1 to mean remove and add
  315. * and also by trig_file_interests_ensure with signum +2 meaning add
  316. * but die if already present.
  317. */
  318. static void
  319. trk_file_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  320. {
  321. struct filenamenode *fnn;
  322. struct trigfileint **search, *tfi;
  323. fnn = trigh.namenode_find(trig, signum <= 0);
  324. if (!fnn) {
  325. assert(signum < 0);
  326. return;
  327. }
  328. for (search = trigh.namenode_interested(fnn);
  329. (tfi = *search);
  330. search = &tfi->samefile_next)
  331. if (tfi->pkg == pkg)
  332. goto found;
  333. /* not found */
  334. if (signum < 0)
  335. return;
  336. tfi = nfmalloc(sizeof(*tfi));
  337. tfi->pkg = pkg;
  338. tfi->fnn = fnn;
  339. tfi->samefile_next = *trigh.namenode_interested(fnn);
  340. *trigh.namenode_interested(fnn) = tfi;
  341. LIST_LINK_TAIL_PART(filetriggers, tfi, inoverall.);
  342. goto edited;
  343. found:
  344. if (signum > 1)
  345. ohshit(_("duplicate file trigger interest for filename `%.250s' "
  346. "and package `%.250s'"), trig, pkg->name);
  347. if (signum > 0)
  348. return;
  349. /* remove it: */
  350. *search = tfi->samefile_next;
  351. LIST_UNLINK_PART(filetriggers, tfi, inoverall.);
  352. edited:
  353. filetriggers_edited = 1;
  354. }
  355. void
  356. trig_file_interests_save(void)
  357. {
  358. struct trigfileint *tfi;
  359. FILE *nf;
  360. if (filetriggers_edited <= 0)
  361. return;
  362. nf = fopen(triggersnewfilefile, "w");
  363. if (!nf)
  364. ohshite(_("unable to create new file triggers file `%.250s'"),
  365. triggersnewfilefile);
  366. push_cleanup(cu_closefile, ~ehflag_normaltidy, NULL, 0, 1, nf);
  367. for (tfi = filetriggers.head; tfi; tfi = tfi->inoverall.next)
  368. fprintf(nf, "%s %s\n", trigh.namenode_name(tfi->fnn),
  369. tfi->pkg->name);
  370. if (ferror(nf) || fclose(nf))
  371. ohshite(_("unable to write new file triggers file `%.250s'"),
  372. triggersnewfilefile);
  373. pop_cleanup(ehflag_normaltidy);
  374. if (rename(triggersnewfilefile, triggersfilefile))
  375. ohshite(_("unable to install new file triggers file as `%.250s'"),
  376. triggersfilefile);
  377. filetriggers_edited = 0;
  378. }
  379. void
  380. trig_file_interests_ensure(void)
  381. {
  382. FILE *f;
  383. char linebuf[1024], *space;
  384. struct pkginfo *pkg;
  385. const char *emsg;
  386. if (filetriggers_edited >= 0)
  387. return;
  388. f = fopen(triggersfilefile, "r");
  389. if (!f) {
  390. if (errno == ENOENT)
  391. goto ok;
  392. ohshite(_("unable to read file triggers file `%.250s'"),
  393. triggersfilefile);
  394. }
  395. push_cleanup(cu_closefile, 0, NULL, 0, 1, f);
  396. while (fgets_checked(linebuf, sizeof(linebuf), f, triggersfilefile) >= 0) {
  397. space = strchr(linebuf, ' ');
  398. if (!space || linebuf[0] != '/')
  399. ohshit(_("syntax error in file triggers file `%.250s'"),
  400. triggersfilefile);
  401. *space++ = 0;
  402. if ((emsg = illegal_packagename(space, NULL)))
  403. ohshit(_("file triggers record mentions illegal "
  404. "package name `%.250s' (for interest in file "
  405. "`%.250s'): %.250s"), space, linebuf, emsg);
  406. pkg = findpackage(space);
  407. trk_file_interest_change(linebuf, pkg, +2);
  408. }
  409. pop_cleanup(ehflag_normaltidy);
  410. ok:
  411. filetriggers_edited = 0;
  412. }
  413. static struct filenamenode *filetriggers_activating;
  414. void
  415. trig_file_activate_byname(const char *trig, struct pkginfo *aw)
  416. {
  417. struct filenamenode *fnn = trigh.namenode_find(trig, 1);
  418. if (fnn)
  419. trig_file_activate(fnn, aw);
  420. }
  421. void
  422. trig_file_activate(struct filenamenode *trig, struct pkginfo *aw)
  423. {
  424. struct trigfileint *tfi;
  425. for (tfi = *trigh.namenode_interested(trig); tfi;
  426. tfi = tfi->samefile_next)
  427. trig_record_activation(tfi->pkg, aw, (char*)trigh.namenode_name(trig));
  428. }
  429. static void
  430. trk_file_activate_start(void)
  431. {
  432. filetriggers_activating = trigh.namenode_find(trig_activating_name, 1);
  433. }
  434. static void
  435. trk_file_activate_awaiter(struct pkginfo *aw)
  436. {
  437. if (!filetriggers_activating)
  438. return;
  439. trig_file_activate(filetriggers_activating, aw);
  440. }
  441. static void
  442. trk_file_activate_done(void)
  443. {
  444. }
  445. TKI_DEFINE(file);
  446. /*---------- trigger control info file ----------*/
  447. static void
  448. trig_cicb_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  449. {
  450. const struct trigkindinfo *tki = trig_classify_byname(trig);
  451. assert(filetriggers_edited >= 0);
  452. tki->interest_change(trig, pkg, signum);
  453. }
  454. void
  455. trig_cicb_interest_delete(const char *trig, void *user)
  456. {
  457. trig_cicb_interest_change(trig, user, -1);
  458. }
  459. void
  460. trig_cicb_interest_add(const char *trig, void *user)
  461. {
  462. trig_cicb_interest_change(trig, user, +1);
  463. }
  464. void
  465. trig_cicb_statuschange_activate(const char *trig, void *user)
  466. {
  467. struct pkginfo *aw = user;
  468. trig_activate_start(trig);
  469. dtki->activate_awaiter(aw);
  470. dtki->activate_done();
  471. }
  472. static void
  473. parse_ci_call(const char *file, const char *cmd, trig_parse_cicb *cb,
  474. const char *trig, void *user)
  475. {
  476. const char *emsg;
  477. emsg = illegal_triggername(trig);
  478. if (emsg)
  479. ohshit(_("triggers ci file `%.250s' contains illegal trigger "
  480. "syntax in trigger name `%.250s': %.250s"),
  481. file, trig, emsg);
  482. if (cb)
  483. cb(trig, user);
  484. }
  485. void
  486. trig_parse_ci(const char *file, trig_parse_cicb *interest,
  487. trig_parse_cicb *activate, void *user)
  488. {
  489. FILE *f;
  490. char linebuf[MAXTRIGDIRECTIVE], *cmd, *spc, *eol;
  491. int l;
  492. f = fopen(file, "r");
  493. if (!f) {
  494. if (errno == ENOENT)
  495. /* No file is just like an empty one. */
  496. return;
  497. ohshite(_("unable to open triggers ci file `%.250s'"), file);
  498. }
  499. push_cleanup(cu_closefile, ~0, NULL, 0, 1, f);
  500. while ((l = fgets_checked(linebuf, sizeof(linebuf), f, file)) >= 0) {
  501. for (cmd = linebuf; cisspace(*cmd); cmd++);
  502. if (*cmd == '#')
  503. continue;
  504. for (eol = linebuf + l; eol > cmd && cisspace(eol[-1]); eol--);
  505. if (eol == cmd)
  506. continue;
  507. *eol = 0;
  508. for (spc = cmd; *spc && !cisspace(*spc); spc++);
  509. if (!*spc)
  510. ohshit(_("triggers ci file contains unknown directive syntax"));
  511. *spc++ = 0;
  512. while (cisspace(*spc))
  513. spc++;
  514. if (!strcmp(cmd, "interest")) {
  515. parse_ci_call(file, cmd, interest, spc, user);
  516. } else if (!strcmp(cmd, "activate")) {
  517. parse_ci_call(file, cmd, activate, spc, user);
  518. } else {
  519. ohshit(_("triggers ci file contains unknown directive `%.250s'"),
  520. cmd);
  521. }
  522. }
  523. pop_cleanup(ehflag_normaltidy); /* fclose */
  524. }
  525. /*---------- Unincorp file incorporation ----------*/
  526. static void
  527. tdm_incorp_trig_begin(const char *trig)
  528. {
  529. trig_activate_start(trig);
  530. }
  531. static void
  532. tdm_incorp_package(const char *awname)
  533. {
  534. struct pkginfo *aw = strcmp(awname, "-") ? findpackage(awname) : NULL;
  535. dtki->activate_awaiter(aw);
  536. }
  537. static void
  538. tdm_incorp_trig_end(void)
  539. {
  540. dtki->activate_done();
  541. }
  542. static const struct trigdefmeths tdm_incorp = {
  543. tdm_incorp_trig_begin,
  544. tdm_incorp_package,
  545. tdm_incorp_trig_end
  546. };
  547. void
  548. trig_incorporate(enum modstatdb_rw cstatus, const char *admindir)
  549. {
  550. int ur;
  551. enum trigdef_updateflags tduf;
  552. trigdef = &tdm_incorp;
  553. trig_file_interests_ensure();
  554. tduf = tduf_nolockok;
  555. if (cstatus >= msdbrw_write) {
  556. tduf |= tduf_write;
  557. if (trigh.transitional_activate)
  558. tduf |= tduf_writeifenoent;
  559. }
  560. ur = trigdef_update_start(tduf, admindir);
  561. if (ur == -1 && cstatus >= msdbrw_write) {
  562. if (mkdir(triggersdir, 0755)) {
  563. if (errno != EEXIST)
  564. ohshite(_("unable to create triggers state"
  565. " directory `%.250s'"), triggersdir);
  566. } else if (chown(triggersdir, 0, 0)) {
  567. ohshite(_("unable to set ownership of triggers state"
  568. " directory `%.250s'"), triggersdir);
  569. }
  570. ur = trigdef_update_start(tduf, admindir);
  571. }
  572. switch (ur) {
  573. case -2:
  574. return;
  575. case -1:
  576. case -3:
  577. if (!trigh.transitional_activate)
  578. return;
  579. /* Fall through. */
  580. case 1:
  581. trigh.transitional_activate(cstatus);
  582. break;
  583. case 2:
  584. /* Read and incorporate triggers. */
  585. trigdef_yylex();
  586. break;
  587. default:
  588. abort();
  589. }
  590. /* Right, that's it. New (empty) Unincopr can be installed. */
  591. trigdef_process_done();
  592. }
  593. /*---------- default hooks ----------*/
  594. struct filenamenode {
  595. struct filenamenode *next;
  596. const char *name;
  597. struct trigfileint *trig_interested;
  598. };
  599. static struct filenamenode *trigger_files;
  600. static struct filenamenode *
  601. th_simple_nn_find(const char *name, int nonew)
  602. {
  603. struct filenamenode *search;
  604. for (search = trigger_files; search; search = search->next)
  605. if (!strcmp(search->name, name))
  606. return search;
  607. /* Not found. */
  608. if (nonew)
  609. return NULL;
  610. search = nfmalloc(sizeof(*search));
  611. search->name = nfstrsave(name);
  612. search->trig_interested = NULL;
  613. search->next = trigger_files;
  614. trigger_files = search;
  615. return search;
  616. }
  617. TRIGHOOKS_DEFINE_NAMENODE_ACCESSORS
  618. struct trig_hooks trigh = {
  619. NULL,
  620. NULL,
  621. th_simple_nn_find,
  622. th_nn_interested,
  623. th_nn_name
  624. };