triglib.c 19 KB

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