triglib.c 21 KB

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