triglib.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  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
  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. /* FIXME: switch to use the generic pkg list for lenny+1 */
  143. struct pkg_list {
  144. struct pkg_list *next;
  145. struct pkginfo *pkg;
  146. };
  147. static struct pkg_list *trig_awaited_pend_head;
  148. void
  149. trig_enqueue_awaited_pend(struct pkginfo *pend)
  150. {
  151. struct pkg_list *tp;
  152. for (tp = trig_awaited_pend_head; tp; tp = tp->next)
  153. if (tp->pkg == pend)
  154. return;
  155. tp = nfmalloc(sizeof(*tp));
  156. tp->pkg = pend;
  157. tp->next = trig_awaited_pend_head;
  158. trig_awaited_pend_head = tp;
  159. }
  160. /*
  161. * Fix up packages in state triggers-awaited w/o the corresponding package
  162. * with pending triggers. This can happen when dpkg was interrupted
  163. * while in modstatdb_note, and the package in triggers-pending had its
  164. * state modified but dpkg could not clearing the awaiters.
  165. *
  166. * XXX: possibly get rid of some of the checks done somewhere else for
  167. * this condition at run-time.
  168. */
  169. void
  170. trig_fixup_awaiters(enum modstatdb_rw cstatus)
  171. {
  172. struct pkg_list *tp;
  173. if (cstatus < msdbrw_write)
  174. return;
  175. for (tp = trig_awaited_pend_head; tp; tp = tp->next)
  176. if (!tp->pkg->trigpend_head)
  177. trig_clear_awaiters(tp->pkg);
  178. trig_awaited_pend_head = NULL;
  179. }
  180. /*---------- generalised handling of trigger kinds ----------*/
  181. static const struct trigkindinfo tki_explicit, tki_file, tki_unknown;
  182. struct trigkindinfo {
  183. /* Only for trig_activate_start. */
  184. void (*activate_start)(void);
  185. /* Rest are for everyone: */
  186. void (*activate_awaiter)(struct pkginfo *pkg /* may be NULL */);
  187. void (*activate_done)(void);
  188. void (*interest_change)(const char *name, struct pkginfo *pkg, int signum);
  189. };
  190. #define TKI_DEFINE(kindname) \
  191. static const struct trigkindinfo tki_##kindname= { \
  192. trk_##kindname##_activate_start, \
  193. trk_##kindname##_activate_awaiter, \
  194. trk_##kindname##_activate_done, \
  195. trk_##kindname##_interest_change \
  196. };
  197. static const struct trigkindinfo *dtki;
  198. /* As passed into activate_start. */
  199. static const char *trig_activating_name;
  200. static const struct trigkindinfo *
  201. trig_classify_byname(const char *name)
  202. {
  203. if (name[0] == '/') {
  204. const char *slash;
  205. slash = name;
  206. while (slash) {
  207. if (slash[1] == 0 || slash[1] == '/')
  208. goto invalid;
  209. slash = strchr(slash + 2, '/');
  210. }
  211. return &tki_file;
  212. }
  213. if (!illegal_packagename(name, NULL) && !strchr(name, '_'))
  214. return &tki_explicit;
  215. invalid:
  216. return &tki_unknown;
  217. }
  218. /* Calling sequence is:
  219. * trig_activate_start(triggername)
  220. * dtki->activate_awaiter(awaiting_package) } zero or more times
  221. * dtki->activate_awaiter(0) } in any order
  222. * dtki->activate_done(0)
  223. */
  224. static void
  225. trig_activate_start(const char *name)
  226. {
  227. dtki = trig_classify_byname(name);
  228. trig_activating_name = name;
  229. dtki->activate_start();
  230. }
  231. /*---------- unknown trigger kinds ----------*/
  232. static void
  233. trk_unknown_activate_start(void)
  234. {
  235. }
  236. static void
  237. trk_unknown_activate_awaiter(struct pkginfo *aw)
  238. {
  239. }
  240. static void
  241. trk_unknown_activate_done(void)
  242. {
  243. }
  244. static void
  245. trk_unknown_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  246. {
  247. ohshit(_("invalid or unknown syntax in trigger name `%.250s'"
  248. " (in trigger interests for package `%.250s')"),
  249. trig, pkg->name);
  250. }
  251. TKI_DEFINE(unknown);
  252. /*---------- explicit triggers ----------*/
  253. static FILE *trk_explicit_f;
  254. static struct varbuf trk_explicit_fn;
  255. static char *trk_explicit_trig;
  256. static void
  257. trk_explicit_activate_done(void)
  258. {
  259. if (trk_explicit_f) {
  260. fclose(trk_explicit_f);
  261. trk_explicit_f = NULL;
  262. }
  263. }
  264. static void
  265. trk_explicit_start(const char *trig)
  266. {
  267. trk_explicit_activate_done();
  268. varbufreset(&trk_explicit_fn);
  269. varbufaddstr(&trk_explicit_fn, triggersdir);
  270. varbufaddstr(&trk_explicit_fn, trig);
  271. varbufaddc(&trk_explicit_fn, 0);
  272. trk_explicit_f = fopen(trk_explicit_fn.buf, "r");
  273. if (!trk_explicit_f) {
  274. if (errno != ENOENT)
  275. ohshite(_("failed to open trigger interest list file `%.250s'"),
  276. trk_explicit_fn.buf);
  277. }
  278. }
  279. static int
  280. trk_explicit_fgets(char *buf, size_t sz)
  281. {
  282. return fgets_checked(buf, sz, trk_explicit_f, trk_explicit_fn.buf);
  283. }
  284. static void
  285. trk_explicit_activate_start(void)
  286. {
  287. trk_explicit_start(trig_activating_name);
  288. trk_explicit_trig = nfstrsave(trig_activating_name);
  289. }
  290. static void
  291. trk_explicit_activate_awaiter(struct pkginfo *aw)
  292. {
  293. char buf[1024];
  294. const char *emsg;
  295. struct pkginfo *pend;
  296. if (!trk_explicit_f)
  297. return;
  298. if (fseek(trk_explicit_f, 0, SEEK_SET))
  299. ohshite(_("failed to rewind trigger interest file `%.250s'"),
  300. trk_explicit_fn.buf);
  301. while (trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
  302. if ((emsg = illegal_packagename(buf, NULL)))
  303. ohshit(_("trigger interest file `%.250s' syntax error; "
  304. "illegal package name `%.250s': %.250s"),
  305. trk_explicit_fn.buf, buf, emsg);
  306. pend = findpackage(buf);
  307. trig_record_activation(pend, aw, trk_explicit_trig);
  308. }
  309. }
  310. static void
  311. trk_explicit_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  312. {
  313. static struct varbuf newfn;
  314. char buf[1024];
  315. FILE *nf;
  316. trk_explicit_start(trig);
  317. varbufreset(&newfn);
  318. varbufprintf(&newfn, "%s/%s.new", triggersdir, trig);
  319. varbufaddc(&newfn, 0);
  320. nf = fopen(newfn.buf, "w");
  321. if (!nf)
  322. ohshite(_("unable to create new trigger interest file `%.250s'"),
  323. newfn.buf);
  324. push_cleanup(cu_closefile, ~ehflag_normaltidy, NULL, 0, 1, nf);
  325. while (trk_explicit_f && trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
  326. if (!strcmp(buf, pkg->name))
  327. continue;
  328. fprintf(nf, "%s\n", buf);
  329. }
  330. if (signum > 0)
  331. fprintf(nf, "%s\n", pkg->name);
  332. if (ferror(nf) || fclose(nf))
  333. ohshite(_("unable to write new trigger interest file `%.250s'"),
  334. newfn.buf);
  335. pop_cleanup(ehflag_normaltidy);
  336. if (rename(newfn.buf, trk_explicit_fn.buf))
  337. ohshite(_("unable to install new trigger interest file `%.250s'"),
  338. trk_explicit_fn.buf);
  339. }
  340. TKI_DEFINE(explicit);
  341. /*---------- file triggers ----------*/
  342. static struct {
  343. struct trigfileint *head, *tail;
  344. } filetriggers;
  345. /*
  346. * Values:
  347. * -1: not read,
  348. * 0: not edited
  349. * 1: edited
  350. */
  351. static int filetriggers_edited = -1;
  352. /* Called by various people with signum -1 and +1 to mean remove and add
  353. * and also by trig_file_interests_ensure with signum +2 meaning add
  354. * but die if already present.
  355. */
  356. static void
  357. trk_file_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  358. {
  359. struct filenamenode *fnn;
  360. struct trigfileint **search, *tfi;
  361. fnn = trigh.namenode_find(trig, signum <= 0);
  362. if (!fnn) {
  363. assert(signum < 0);
  364. return;
  365. }
  366. for (search = trigh.namenode_interested(fnn);
  367. (tfi = *search);
  368. search = &tfi->samefile_next)
  369. if (tfi->pkg == pkg)
  370. goto found;
  371. /* not found */
  372. if (signum < 0)
  373. return;
  374. tfi = nfmalloc(sizeof(*tfi));
  375. tfi->pkg = pkg;
  376. tfi->fnn = fnn;
  377. tfi->samefile_next = *trigh.namenode_interested(fnn);
  378. *trigh.namenode_interested(fnn) = tfi;
  379. LIST_LINK_TAIL_PART(filetriggers, tfi, inoverall.);
  380. goto edited;
  381. found:
  382. if (signum > 1)
  383. ohshit(_("duplicate file trigger interest for filename `%.250s' "
  384. "and package `%.250s'"), trig, pkg->name);
  385. if (signum > 0)
  386. return;
  387. /* remove it: */
  388. *search = tfi->samefile_next;
  389. LIST_UNLINK_PART(filetriggers, tfi, inoverall.);
  390. edited:
  391. filetriggers_edited = 1;
  392. }
  393. void
  394. trig_file_interests_save(void)
  395. {
  396. struct trigfileint *tfi;
  397. FILE *nf;
  398. if (filetriggers_edited <= 0)
  399. return;
  400. nf = fopen(triggersnewfilefile, "w");
  401. if (!nf)
  402. ohshite(_("unable to create new file triggers file `%.250s'"),
  403. triggersnewfilefile);
  404. push_cleanup(cu_closefile, ~ehflag_normaltidy, NULL, 0, 1, nf);
  405. for (tfi = filetriggers.head; tfi; tfi = tfi->inoverall.next)
  406. fprintf(nf, "%s %s\n", trigh.namenode_name(tfi->fnn),
  407. tfi->pkg->name);
  408. if (ferror(nf) || fclose(nf))
  409. ohshite(_("unable to write new file triggers file `%.250s'"),
  410. triggersnewfilefile);
  411. pop_cleanup(ehflag_normaltidy);
  412. if (rename(triggersnewfilefile, triggersfilefile))
  413. ohshite(_("unable to install new file triggers file as `%.250s'"),
  414. triggersfilefile);
  415. filetriggers_edited = 0;
  416. }
  417. void
  418. trig_file_interests_ensure(void)
  419. {
  420. FILE *f;
  421. char linebuf[1024], *space;
  422. struct pkginfo *pkg;
  423. const char *emsg;
  424. if (filetriggers_edited >= 0)
  425. return;
  426. f = fopen(triggersfilefile, "r");
  427. if (!f) {
  428. if (errno == ENOENT)
  429. goto ok;
  430. ohshite(_("unable to read file triggers file `%.250s'"),
  431. triggersfilefile);
  432. }
  433. push_cleanup(cu_closefile, ~0, NULL, 0, 1, f);
  434. while (fgets_checked(linebuf, sizeof(linebuf), f, triggersfilefile) >= 0) {
  435. space = strchr(linebuf, ' ');
  436. if (!space || linebuf[0] != '/')
  437. ohshit(_("syntax error in file triggers file `%.250s'"),
  438. triggersfilefile);
  439. *space++ = 0;
  440. if ((emsg = illegal_packagename(space, NULL)))
  441. ohshit(_("file triggers record mentions illegal "
  442. "package name `%.250s' (for interest in file "
  443. "`%.250s'): %.250s"), space, linebuf, emsg);
  444. pkg = findpackage(space);
  445. trk_file_interest_change(linebuf, pkg, +2);
  446. }
  447. pop_cleanup(ehflag_normaltidy);
  448. ok:
  449. filetriggers_edited = 0;
  450. }
  451. static struct filenamenode *filetriggers_activating;
  452. void
  453. trig_file_activate_byname(const char *trig, struct pkginfo *aw)
  454. {
  455. struct filenamenode *fnn = trigh.namenode_find(trig, 1);
  456. if (fnn)
  457. trig_file_activate(fnn, aw);
  458. }
  459. void
  460. trig_file_activate(struct filenamenode *trig, struct pkginfo *aw)
  461. {
  462. struct trigfileint *tfi;
  463. for (tfi = *trigh.namenode_interested(trig); tfi;
  464. tfi = tfi->samefile_next)
  465. trig_record_activation(tfi->pkg, aw, (char*)trigh.namenode_name(trig));
  466. }
  467. static void
  468. trk_file_activate_start(void)
  469. {
  470. filetriggers_activating = trigh.namenode_find(trig_activating_name, 1);
  471. }
  472. static void
  473. trk_file_activate_awaiter(struct pkginfo *aw)
  474. {
  475. if (!filetriggers_activating)
  476. return;
  477. trig_file_activate(filetriggers_activating, aw);
  478. }
  479. static void
  480. trk_file_activate_done(void)
  481. {
  482. }
  483. TKI_DEFINE(file);
  484. /*---------- trigger control info file ----------*/
  485. static void
  486. trig_cicb_interest_change(const char *trig, struct pkginfo *pkg, int signum)
  487. {
  488. const struct trigkindinfo *tki = trig_classify_byname(trig);
  489. assert(filetriggers_edited >= 0);
  490. tki->interest_change(trig, pkg, signum);
  491. }
  492. void
  493. trig_cicb_interest_delete(const char *trig, void *user)
  494. {
  495. trig_cicb_interest_change(trig, user, -1);
  496. }
  497. void
  498. trig_cicb_interest_add(const char *trig, void *user)
  499. {
  500. trig_cicb_interest_change(trig, user, +1);
  501. }
  502. void
  503. trig_cicb_statuschange_activate(const char *trig, void *user)
  504. {
  505. struct pkginfo *aw = user;
  506. trig_activate_start(trig);
  507. dtki->activate_awaiter(aw);
  508. dtki->activate_done();
  509. }
  510. static void
  511. parse_ci_call(const char *file, const char *cmd, trig_parse_cicb *cb,
  512. const char *trig, void *user)
  513. {
  514. const char *emsg;
  515. emsg = illegal_triggername(trig);
  516. if (emsg)
  517. ohshit(_("triggers ci file `%.250s' contains illegal trigger "
  518. "syntax in trigger name `%.250s': %.250s"),
  519. file, trig, emsg);
  520. if (cb)
  521. cb(trig, user);
  522. }
  523. void
  524. trig_parse_ci(const char *file, trig_parse_cicb *interest,
  525. trig_parse_cicb *activate, void *user)
  526. {
  527. FILE *f;
  528. char linebuf[MAXTRIGDIRECTIVE], *cmd, *spc, *eol;
  529. int l;
  530. f = fopen(file, "r");
  531. if (!f) {
  532. if (errno == ENOENT)
  533. /* No file is just like an empty one. */
  534. return;
  535. ohshite(_("unable to open triggers ci file `%.250s'"), file);
  536. }
  537. push_cleanup(cu_closefile, ~0, NULL, 0, 1, f);
  538. while ((l = fgets_checked(linebuf, sizeof(linebuf), f, file)) >= 0) {
  539. for (cmd = linebuf; cisspace(*cmd); cmd++);
  540. if (*cmd == '#')
  541. continue;
  542. for (eol = linebuf + l; eol > cmd && cisspace(eol[-1]); eol--);
  543. if (eol == cmd)
  544. continue;
  545. *eol = 0;
  546. for (spc = cmd; *spc && !cisspace(*spc); spc++);
  547. if (!*spc)
  548. ohshit(_("triggers ci file contains unknown directive syntax"));
  549. *spc++ = 0;
  550. while (cisspace(*spc))
  551. spc++;
  552. if (!strcmp(cmd, "interest")) {
  553. parse_ci_call(file, cmd, interest, spc, user);
  554. } else if (!strcmp(cmd, "activate")) {
  555. parse_ci_call(file, cmd, activate, spc, user);
  556. } else {
  557. ohshit(_("triggers ci file contains unknown directive `%.250s'"),
  558. cmd);
  559. }
  560. }
  561. pop_cleanup(ehflag_normaltidy); /* fclose */
  562. }
  563. /*---------- Unincorp file incorporation ----------*/
  564. static void
  565. tdm_incorp_trig_begin(const char *trig)
  566. {
  567. trig_activate_start(trig);
  568. }
  569. static void
  570. tdm_incorp_package(const char *awname)
  571. {
  572. struct pkginfo *aw = strcmp(awname, "-") ? findpackage(awname) : NULL;
  573. dtki->activate_awaiter(aw);
  574. }
  575. static void
  576. tdm_incorp_trig_end(void)
  577. {
  578. dtki->activate_done();
  579. }
  580. static const struct trigdefmeths tdm_incorp = {
  581. tdm_incorp_trig_begin,
  582. tdm_incorp_package,
  583. tdm_incorp_trig_end
  584. };
  585. void
  586. trig_incorporate(enum modstatdb_rw cstatus, const char *admindir)
  587. {
  588. int ur;
  589. enum trigdef_updateflags tduf;
  590. trigdef = &tdm_incorp;
  591. trig_file_interests_ensure();
  592. tduf = tduf_nolockok;
  593. if (cstatus >= msdbrw_write) {
  594. tduf |= tduf_write;
  595. if (trigh.transitional_activate)
  596. tduf |= tduf_writeifenoent;
  597. }
  598. ur = trigdef_update_start(tduf, admindir);
  599. if (ur == -1 && cstatus >= msdbrw_write) {
  600. if (mkdir(triggersdir, 0755)) {
  601. if (errno != EEXIST)
  602. ohshite(_("unable to create triggers state"
  603. " directory `%.250s'"), triggersdir);
  604. } else if (chown(triggersdir, 0, 0)) {
  605. ohshite(_("unable to set ownership of triggers state"
  606. " directory `%.250s'"), triggersdir);
  607. }
  608. ur = trigdef_update_start(tduf, admindir);
  609. }
  610. switch (ur) {
  611. case -2:
  612. return;
  613. case -1:
  614. case -3:
  615. if (!trigh.transitional_activate)
  616. return;
  617. /* Fall through. */
  618. case 1:
  619. trigh.transitional_activate(cstatus);
  620. break;
  621. case 2:
  622. /* Read and incorporate triggers. */
  623. trigdef_yylex();
  624. break;
  625. default:
  626. abort();
  627. }
  628. /* Right, that's it. New (empty) Unincorp can be installed. */
  629. trigdef_process_done();
  630. }
  631. /*---------- default hooks ----------*/
  632. struct filenamenode {
  633. struct filenamenode *next;
  634. const char *name;
  635. struct trigfileint *trig_interested;
  636. };
  637. static struct filenamenode *trigger_files;
  638. static struct filenamenode *
  639. th_simple_nn_find(const char *name, int nonew)
  640. {
  641. struct filenamenode *search;
  642. for (search = trigger_files; search; search = search->next)
  643. if (!strcmp(search->name, name))
  644. return search;
  645. /* Not found. */
  646. if (nonew)
  647. return NULL;
  648. search = nfmalloc(sizeof(*search));
  649. search->name = nfstrsave(name);
  650. search->trig_interested = NULL;
  651. search->next = trigger_files;
  652. trigger_files = search;
  653. return search;
  654. }
  655. TRIGHOOKS_DEFINE_NAMENODE_ACCESSORS
  656. struct trig_hooks trigh = {
  657. NULL,
  658. NULL,
  659. th_simple_nn_find,
  660. th_nn_interested,
  661. th_nn_name
  662. };