triglib.c 21 KB

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