/ libpkg / pkg_event.c
pkg_event.c
   1  /*-
   2   * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
   3   * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
   4   * Copyright (c) 2015 Matthew Seaman <matthew@FreeBSD.org>
   5   * Copyright (c) 2023 Serenity Cyber Security, LLC <license@futurecrew.ru>
   6   *                    Author: Gleb Popov <arrowd@FreeBSD.org>
   7   * All rights reserved.
   8   *
   9   * Redistribution and use in source and binary forms, with or without
  10   * modification, are permitted provided that the following conditions
  11   * are met:
  12   * 1. Redistributions of source code must retain the above copyright
  13   *    notice, this list of conditions and the following disclaimer
  14   *    in this position and unchanged.
  15   * 2. Redistributions in binary form must reproduce the above copyright
  16   *    notice, this list of conditions and the following disclaimer in the
  17   *    documentation and/or other materials provided with the distribution.
  18   *
  19   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  20   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22   * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  23   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29   */
  30  
  31  #include <errno.h>
  32  #include <string.h>
  33  #include <syslog.h>
  34  #include <xstring.h>
  35  
  36  #include "pkg.h"
  37  #include "private/pkg.h"
  38  #include "private/event.h"
  39  
  40  static pkg_event_cb _cb = NULL;
  41  static void *_data = NULL;
  42  
  43  static void
  44  pipeevent(struct pkg_event *ev)
  45  {
  46  	int i;
  47  	struct pkg_dep *dep = NULL;
  48  	xstring *msg;
  49  	struct pkg_event_conflict *cur_conflict;
  50  	if (ctx.eventpipe < 0)
  51  		return;
  52  
  53  	msg = xstring_new();
  54  
  55  	switch(ev->type) {
  56  	case PKG_EVENT_ERRNO:
  57  		fprintf(msg->fp, "{ \"type\": \"ERROR\", "
  58  		    "\"data\": {"
  59  		    "\"msg\": \"%s(%s): %s\","
  60  		    "\"errno\": %d}}",
  61  		    json_escape(ev->e_errno.func),
  62  		    json_escape(ev->e_errno.arg),
  63  		    json_escape(strerror(ev->e_errno.no)),
  64  		    ev->e_errno.no);
  65  		break;
  66  	case PKG_EVENT_ERROR:
  67  		fprintf(msg->fp, "{ \"type\": \"ERROR\", "
  68  		    "\"data\": {\"msg\": \"%s\"}}",
  69  		    json_escape(ev->e_pkg_error.msg));
  70  		break;
  71  	case PKG_EVENT_NOTICE:
  72  		fprintf(msg->fp, "{ \"type\": \"NOTICE\", "
  73  		    "\"data\": {\"msg\": \"%s\"}}",
  74  		    json_escape(ev->e_pkg_notice.msg));
  75  		break;
  76  	case PKG_EVENT_DEVELOPER_MODE:
  77  		fprintf(msg->fp, "{ \"type\": \"ERROR\", "
  78  		    "\"data\": {\"msg\": \"DEVELOPER_MODE: %s\"}}",
  79  		    json_escape(ev->e_pkg_error.msg));
  80  		break;
  81  	case PKG_EVENT_UPDATE_ADD:
  82  		fprintf(msg->fp, "{ \"type\": \"INFO_UPDATE_ADD\", "
  83  		    "\"data\": { "
  84  		    "\"fetched\": %d, "
  85  		    "\"total\": %d"
  86  		    "}}",
  87  		    ev->e_upd_add.done,
  88  		    ev->e_upd_add.total
  89  		    );
  90  		break;
  91  	case PKG_EVENT_UPDATE_REMOVE:
  92  		fprintf(msg->fp, "{ \"type\": \"INFO_UPDATE_REMOVE\", "
  93  		    "\"data\": { "
  94  		    "\"fetched\": %d, "
  95  		    "\"total\": %d"
  96  		    "}}",
  97  		    ev->e_upd_remove.done,
  98  		    ev->e_upd_remove.total
  99  		    );
 100  		break;
 101  	case PKG_EVENT_FETCH_BEGIN:
 102  		fprintf(msg->fp, "{ \"type\": \"INFO_FETCH_BEGIN\", "
 103  		    "\"data\": { "
 104  		    "\"url\": \"%s\" "
 105  		    "}}",
 106  		    json_escape(ev->e_fetching.url)
 107  		    );
 108  		break;
 109  	case PKG_EVENT_FETCH_FINISHED:
 110  		fprintf(msg->fp, "{ \"type\": \"INFO_FETCH_FINISHED\", "
 111  		    "\"data\": { "
 112  		    "\"url\": \"%s\" "
 113  		    "}}",
 114  		    json_escape(ev->e_fetching.url)
 115  		    );
 116  		break;
 117  	case PKG_EVENT_INSTALL_BEGIN:
 118  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_INSTALL_BEGIN\", "
 119  		    "\"data\": { "
 120  		    "\"pkgname\": \"%n\", "
 121  		    "\"pkgversion\": \"%v\""
 122  		    "}}", ev->e_install_begin.pkg, ev->e_install_begin.pkg);
 123  		break;
 124  	case PKG_EVENT_EXTRACT_BEGIN:
 125  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_EXTRACT_BEGIN\", "
 126  		    "\"data\": { "
 127  		    "\"pkgname\": \"%n\", "
 128  		    "\"pkgversion\": \"%v\""
 129  		    "}}", ev->e_extract_begin.pkg, ev->e_extract_begin.pkg);
 130  		break;
 131  	case PKG_EVENT_EXTRACT_FINISHED:
 132  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_EXTRACT_FINISHED\", "
 133  		    "\"data\": { "
 134  		    "\"pkgname\": \"%n\", "
 135  		    "\"pkgversion\": \"%v\""
 136  		    "}}", ev->e_extract_finished.pkg, ev->e_extract_finished.pkg);
 137  		break;
 138  	case PKG_EVENT_INSTALL_FINISHED: {
 139  		char *msgjson = pkg_has_message(ev->e_install_finished.pkg) ?
 140  		    pkg_message_to_str(ev->e_install_finished.pkg) : NULL;
 141  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_INSTALL_FINISHED\", "
 142  		    "\"data\": { "
 143  		    "\"pkgname\": \"%n\", "
 144  		    "\"pkgversion\": \"%v\", "
 145  		    "\"message\": %S"
 146  		    "}}",
 147  		    ev->e_install_finished.pkg,
 148  		    ev->e_install_finished.pkg,
 149  		    msgjson != NULL ? msgjson : "\"\"");
 150  		free(msgjson);
 151  		break;
 152  	}
 153  	case PKG_EVENT_INTEGRITYCHECK_BEGIN:
 154  		fputs("{ \"type\": \"INFO_INTEGRITYCHECK_BEGIN\", "
 155  		    "\"data\": {}}", msg->fp);
 156  		break;
 157  	case PKG_EVENT_INTEGRITYCHECK_CONFLICT:
 158  		fprintf(msg->fp, "{ \"type\": \"INFO_INTEGRITYCHECK_CONFLICT\","
 159  			"\"data\": { "
 160  			"\"pkguid\": \"%s\", "
 161  			"\"pkgpath\": \"%s\", "
 162  			"\"conflicts\": [",
 163  			ev->e_integrity_conflict.pkg_uid,
 164  			ev->e_integrity_conflict.pkg_path);
 165  		cur_conflict = ev->e_integrity_conflict.conflicts;
 166  		while (cur_conflict != NULL) {
 167  			if (cur_conflict->next != NULL) {
 168  				fprintf(msg->fp, "{\"uid\":\"%s\"},",
 169  						cur_conflict->uid);
 170  			}
 171  			else {
 172  				fprintf(msg->fp, "{\"uid\":\"%s\"}",
 173  						cur_conflict->uid);
 174  				break;
 175  			}
 176  			cur_conflict = cur_conflict->next;
 177  		}
 178  		fputs("]}}", msg->fp);
 179  		break;
 180  	case PKG_EVENT_INTEGRITYCHECK_FINISHED:
 181  		fprintf(msg->fp, "{ \"type\": \"INFO_INTEGRITYCHECK_FINISHED\", "
 182  		    "\"data\": {\"conflicting\": %d}}",
 183  		    ev->e_integrity_finished.conflicting);
 184  		break;
 185  	case PKG_EVENT_DEINSTALL_BEGIN:
 186  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_DEINSTALL_BEGIN\", "
 187  		    "\"data\": { "
 188  		    "\"pkgname\": \"%n\", "
 189  		    "\"pkgversion\": \"%v\""
 190  		    "}}",
 191  		    ev->e_deinstall_begin.pkg,
 192  		    ev->e_deinstall_begin.pkg);
 193  		break;
 194  	case PKG_EVENT_DEINSTALL_FINISHED:
 195  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_DEINSTALL_FINISHED\", "
 196  		    "\"data\": { "
 197  		    "\"pkgname\": \"%n\", "
 198  		    "\"pkgversion\": \"%v\""
 199  		    "}}",
 200  		    ev->e_deinstall_finished.pkg,
 201  		    ev->e_deinstall_finished.pkg);
 202  		break;
 203  	case PKG_EVENT_UPGRADE_BEGIN:
 204  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_UPGRADE_BEGIN\", "
 205  		    "\"data\": { "
 206  		    "\"pkgname\": \"%n\", "
 207  		    "\"pkgversion\": \"%v\" ,"
 208  		    "\"pkgnewversion\": \"%v\""
 209  		    "}}",
 210  		    ev->e_upgrade_begin.o,
 211  		    ev->e_upgrade_begin.o,
 212  		    ev->e_upgrade_begin.n);
 213  		break;
 214  	case PKG_EVENT_UPGRADE_FINISHED:
 215  		pkg_fprintf(msg->fp, "{ \"type\": \"INFO_UPGRADE_FINISHED\", "
 216  		    "\"data\": { "
 217  		    "\"pkgname\": \"%n\", "
 218  		    "\"pkgversion\": \"%v\" ,"
 219  		    "\"pkgnewversion\": \"%v\""
 220  		    "}}",
 221  		    ev->e_upgrade_finished.o,
 222  		    ev->e_upgrade_finished.o,
 223  		    ev->e_upgrade_finished.n);
 224  		break;
 225  	case PKG_EVENT_LOCKED:
 226  		pkg_fprintf(msg->fp, "{ \"type\": \"ERROR_LOCKED\", "
 227  		    "\"data\": { "
 228  		    "\"pkgname\": \"%n\", "
 229  		    "\"pkgversion\": \"%n\""
 230  		    "}}",
 231  		    ev->e_locked.pkg,
 232  		    ev->e_locked.pkg);
 233  		break;
 234  	case PKG_EVENT_REQUIRED:
 235  		pkg_fprintf(msg->fp, "{ \"type\": \"ERROR_REQUIRED\", "
 236  		    "\"data\": { "
 237  		    "\"pkgname\": \"%n\", "
 238  		    "\"pkgversion\": \"%v\", "
 239  		    "\"force\": %S, "
 240  		    "\"required_by\": [",
 241  		    ev->e_required.pkg,
 242  		    ev->e_required.pkg,
 243  		    ev->e_required.force == 1 ? "true": "false");
 244  		while (pkg_rdeps(ev->e_required.pkg, &dep) == EPKG_OK)
 245  			fprintf(msg->fp, "{ \"pkgname\": \"%s\", "
 246  			    "\"pkgversion\": \"%s\" }, ",
 247  			    dep->name, dep->version);
 248  		int c = 0;
 249  		ungetc(c, msg->fp);
 250  		ungetc(c, msg->fp);
 251  		fputs("]}}", msg->fp);
 252  		break;
 253  	case PKG_EVENT_ALREADY_INSTALLED:
 254  		pkg_fprintf(msg->fp, "{ \"type\": \"ERROR_ALREADY_INSTALLED\", "
 255  		    "\"data\": { "
 256  		    "\"pkgname\": \"%n\", "
 257  		    "\"pkgversion\": \"%v\""
 258  		    "}}",
 259  		    ev->e_already_installed.pkg,
 260  		    ev->e_already_installed.pkg);
 261  		break;
 262  	case PKG_EVENT_MISSING_DEP:
 263  		fprintf(msg->fp, "{ \"type\": \"ERROR_MISSING_DEP\", "
 264  		    "\"data\": { "
 265  		    "\"depname\": \"%s\", "
 266  		    "\"depversion\": \"%s\""
 267  		    "}}" ,
 268  		    ev->e_missing_dep.dep->name,
 269  		    ev->e_missing_dep.dep->version);
 270  		break;
 271  	case PKG_EVENT_NOREMOTEDB:
 272  		fprintf(msg->fp, "{ \"type\": \"ERROR_NOREMOTEDB\", "
 273  		    "\"data\": { "
 274  		    "\"url\": \"%s\" "
 275  		    "}}" ,
 276  		    ev->e_remotedb.repo);
 277  		break;
 278  	case PKG_EVENT_NOLOCALDB:
 279  		fputs("{ \"type\": \"ERROR_NOLOCALDB\", \"data\": {}} ",
 280  		    msg->fp);
 281  		break;
 282  	case PKG_EVENT_NEWPKGVERSION:
 283  		fputs("{ \"type\": \"INFO_NEWPKGVERSION\", \"data\": {}} ",
 284  		    msg->fp);
 285  		break;
 286  	case PKG_EVENT_FILE_MISMATCH:
 287  		pkg_fprintf(msg->fp, "{ \"type\": \"ERROR_FILE_MISMATCH\", "
 288  		    "\"data\": { "
 289  		    "\"pkgname\": \"%n\", "
 290  		    "\"pkgversion\": \"%v\", "
 291  		    "\"path\": \"%S\""
 292  		    "}}",
 293  		    ev->e_file_mismatch.pkg,
 294  		    ev->e_file_mismatch.pkg,
 295  		    json_escape(ev->e_file_mismatch.file->path));
 296  		break;
 297  	case PKG_EVENT_PLUGIN_ERRNO:
 298  		fprintf(msg->fp, "{ \"type\": \"ERROR_PLUGIN\", "
 299  		    "\"data\": {"
 300  		    "\"plugin\": \"%s\", "
 301  		    "\"msg\": \"%s(%s): %s\","
 302  		    "\"errno\": %d"
 303  		    "}}",
 304  		    pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
 305  		    json_escape(ev->e_plugin_errno.func),
 306  		    json_escape(ev->e_plugin_errno.arg),
 307  		    json_escape(strerror(ev->e_plugin_errno.no)),
 308  		    ev->e_plugin_errno.no);
 309  		break;
 310  	case PKG_EVENT_PLUGIN_ERROR:
 311  		fprintf(msg->fp, "{ \"type\": \"ERROR_PLUGIN\", "
 312  		    "\"data\": {"
 313  		    "\"plugin\": \"%s\", "
 314  		    "\"msg\": \"%s\""
 315  		    "}}",
 316  		    pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME),
 317  		    json_escape(ev->e_plugin_error.msg));
 318  		break;
 319  	case PKG_EVENT_PLUGIN_INFO:
 320  		fprintf(msg->fp, "{ \"type\": \"INFO_PLUGIN\", "
 321  		    "\"data\": {"
 322  		    "\"plugin\": \"%s\", "
 323  		    "\"msg\": \"%s\""
 324  		    "}}",
 325  		    pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME),
 326  		    json_escape(ev->e_plugin_info.msg));
 327  		break;
 328  	case PKG_EVENT_INCREMENTAL_UPDATE:
 329  		fprintf(msg->fp, "{ \"type\": \"INFO_INCREMENTAL_UPDATE\", "
 330  		    "\"data\": {"
 331  		        "\"name\": \"%s\", "
 332  			"\"processed\": %d"
 333  			"}}", ev->e_incremental_update.reponame,
 334  			ev->e_incremental_update.processed);
 335  		break;
 336  	case PKG_EVENT_QUERY_YESNO:
 337  		fprintf(msg->fp, "{ \"type\": \"QUERY_YESNO\", "
 338  		    "\"data\": {"
 339  			"\"msg\": \"%s\","
 340  			"\"default\": \"%d\""
 341  			"}}", ev->e_query_yesno.msg,
 342  			ev->e_query_yesno.deft);
 343  		break;
 344  	case PKG_EVENT_QUERY_SELECT:
 345  		fprintf(msg->fp, "{ \"type\": \"QUERY_SELECT\", "
 346  		    "\"data\": {"
 347  			"\"msg\": \"%s\","
 348  			"\"ncnt\": \"%d\","
 349  			"\"default\": \"%d\","
 350  			"\"items\": ["
 351  			, ev->e_query_select.msg,
 352  			ev->e_query_select.ncnt,
 353  			ev->e_query_select.deft);
 354  		for (i = 0; i < ev->e_query_select.ncnt - 1; i++)
 355  		{
 356  			fprintf(msg->fp, "{ \"text\": \"%s\" },",
 357  				ev->e_query_select.items[i]);
 358  		}
 359  		fprintf(msg->fp, "{ \"text\": \"%s\" } ] }}",
 360  			ev->e_query_select.items[i]);
 361  		break;
 362  	case PKG_EVENT_PROGRESS_START:
 363  		fputs("{ \"type\": \"INFO_PROGRESS_START\", \"data\": {}}",
 364  		    msg->fp);
 365  		break;
 366  	case PKG_EVENT_PROGRESS_TICK:
 367  		fprintf(msg->fp, "{ \"type\": \"INFO_PROGRESS_TICK\", "
 368  		  "\"data\": { \"current\": %jd, \"total\" : %jd}}",
 369  		  (intmax_t)ev->e_progress_tick.current,
 370  		  (intmax_t)ev->e_progress_tick.total);
 371  		break;
 372  	case PKG_EVENT_TRIGGERS_BEGIN:
 373  		fputs("{ \"type\": \"INFO_TRIGGERS_BEGIN\", \"data\": {}}",
 374  		    msg->fp);
 375  		break;
 376  	case PKG_EVENT_TRIGGERS_FINISHED:
 377  		fputs("{ \"type\": \"INFO_TRIGGERS_FINISHED\", \"data\": {}}",
 378  		    msg->fp);
 379  		break;
 380  	case PKG_EVENT_TRIGGER:
 381  		fprintf(msg->fp, "{ \"type\": \"INFO_TRIGGER\", \"data\": { "
 382  		    "\"cleanup\": %s, \"name\": \"%s\" }}",
 383  		    ev->e_trigger.cleanup ? "true" : "false",
 384  		    ev->e_trigger.name);
 385  	case PKG_EVENT_BACKUP:
 386  	case PKG_EVENT_RESTORE:
 387  		break;
 388  	default:
 389  		break;
 390  	}
 391  	fflush(msg->fp);
 392  	dprintf(ctx.eventpipe, "%s\n", msg->buf);
 393  	xstring_free(msg);
 394  }
 395  
 396  void
 397  pkg_event_register(pkg_event_cb cb, void *data)
 398  {
 399  	_cb = cb;
 400  	_data = data;
 401  }
 402  
 403  static int
 404  pkg_emit_event(struct pkg_event *ev)
 405  {
 406  	int ret = 0;
 407  	pkg_plugins_hook_run(PKG_PLUGIN_HOOK_EVENT, ev, NULL);
 408  	if (_cb != NULL)
 409  		ret = _cb(_data, ev);
 410  	pipeevent(ev);
 411  	return (ret);
 412  }
 413  
 414  void
 415  pkg_emit_error(const char *fmt, ...)
 416  {
 417  	struct pkg_event ev;
 418  	va_list ap;
 419  
 420  	ev.type = PKG_EVENT_ERROR;
 421  
 422  	va_start(ap, fmt);
 423  	vasprintf(&ev.e_pkg_error.msg, fmt, ap);
 424  	va_end(ap);
 425  
 426  	pkg_emit_event(&ev);
 427  	free(ev.e_pkg_error.msg);
 428  }
 429  
 430  void
 431  pkg_emit_notice(const char *fmt, ...)
 432  {
 433  	struct pkg_event ev;
 434  	va_list ap;
 435  
 436  	ev.type = PKG_EVENT_NOTICE;
 437  
 438  	va_start(ap, fmt);
 439  	vasprintf(&ev.e_pkg_notice.msg, fmt, ap);
 440  	va_end(ap);
 441  
 442  	pkg_emit_event(&ev);
 443  	free(ev.e_pkg_error.msg);
 444  }
 445  
 446  void
 447  pkg_emit_developer_mode(const char *fmt, ...)
 448  {
 449  	struct pkg_event ev;
 450  	va_list ap;
 451  
 452  	ev.type = PKG_EVENT_DEVELOPER_MODE;
 453  
 454  	va_start(ap, fmt);
 455  	vasprintf(&ev.e_pkg_error.msg, fmt, ap);
 456  	va_end(ap);
 457  
 458  	pkg_emit_event(&ev);
 459  	free(ev.e_pkg_error.msg);
 460  }
 461  
 462  void
 463  pkg_emit_errno(const char *func, const char *arg)
 464  {
 465  	struct pkg_event ev;
 466  
 467  	ev.type = PKG_EVENT_ERRNO;
 468  	ev.e_errno.func = func;
 469  	ev.e_errno.arg = arg;
 470  	ev.e_errno.no = errno;
 471  
 472  	pkg_emit_event(&ev);
 473  }
 474  
 475  void
 476  pkg_emit_pkg_errno(pkg_error_t err, const char *func, const char *arg)
 477  {
 478  	struct pkg_event ev;
 479  
 480  	ev.type = PKG_EVENT_PKG_ERRNO;
 481  	ev.e_errno.func = func;
 482  	ev.e_errno.arg = arg;
 483  	ev.e_errno.no = err;
 484  
 485  	pkg_emit_event(&ev);
 486  }
 487  
 488  void
 489  pkg_emit_already_installed(struct pkg *p)
 490  {
 491  	struct pkg_event ev;
 492  
 493  	ev.type = PKG_EVENT_ALREADY_INSTALLED;
 494  	ev.e_already_installed.pkg = p;
 495  
 496  	pkg_emit_event(&ev);
 497  }
 498  
 499  void
 500  pkg_emit_fetch_begin(const char *url)
 501  {
 502  	struct pkg_event ev;
 503  
 504  	ev.type = PKG_EVENT_FETCH_BEGIN;
 505  	ev.e_fetching.url = url;
 506  
 507  	pkg_emit_event(&ev);
 508  }
 509  
 510  void
 511  pkg_emit_fetch_finished(const char *url)
 512  {
 513  	struct pkg_event ev;
 514  
 515  	ev.type = PKG_EVENT_FETCH_FINISHED;
 516  	ev.e_fetching.url = url;
 517  
 518  	pkg_emit_event(&ev);
 519  }
 520  
 521  void
 522  pkg_emit_update_remove(int total, int done)
 523  {
 524  	struct pkg_event ev;
 525  
 526  	ev.type = PKG_EVENT_UPDATE_REMOVE;
 527  	ev.e_upd_remove.total = total;
 528  	ev.e_upd_remove.done = done;
 529  
 530  	pkg_emit_event(&ev);
 531  }
 532  
 533  
 534  void
 535  pkg_emit_update_add(int total, int done)
 536  {
 537  	struct pkg_event ev;
 538  
 539  	ev.type = PKG_EVENT_UPDATE_ADD;
 540  	ev.e_upd_add.total = total;
 541  	ev.e_upd_add.done = done;
 542  
 543  	pkg_emit_event(&ev);
 544  }
 545  
 546  void
 547  pkg_emit_install_begin(struct pkg *p)
 548  {
 549  	struct pkg_event ev;
 550  
 551  	ev.type = PKG_EVENT_INSTALL_BEGIN;
 552  	ev.e_install_begin.pkg = p;
 553  
 554  	pkg_emit_event(&ev);
 555  }
 556  
 557  void
 558  pkg_emit_install_finished(struct pkg *p, struct pkg *old)
 559  {
 560  	struct pkg_event ev;
 561  	bool syslog_enabled = false;
 562  
 563  	ev.type = PKG_EVENT_INSTALL_FINISHED;
 564  	ev.e_install_finished.pkg = p;
 565  	ev.e_install_finished.old = old;
 566  
 567  	syslog_enabled = pkg_object_bool(pkg_config_get("SYSLOG"));
 568  	if (syslog_enabled) {
 569  		syslog(LOG_NOTICE, "%s-%s installed",
 570  		    p->name, p->version);
 571  	}
 572  
 573  	pkg_emit_event(&ev);
 574  }
 575  
 576  void
 577  pkg_emit_add_deps_begin(struct pkg *p)
 578  {
 579  	struct pkg_event ev;
 580  
 581  	ev.type = PKG_EVENT_ADD_DEPS_BEGIN;
 582  	ev.e_add_deps_begin.pkg = p;
 583  
 584  	pkg_emit_event(&ev);
 585  }
 586  
 587  void
 588  pkg_emit_add_deps_finished(struct pkg *p)
 589  {
 590  	struct pkg_event ev;
 591  
 592  	ev.type = PKG_EVENT_ADD_DEPS_FINISHED;
 593  	ev.e_add_deps_finished.pkg = p;
 594  
 595  	pkg_emit_event(&ev);
 596  }
 597  
 598  void
 599  pkg_emit_extract_begin(struct pkg *p)
 600  {
 601  	struct pkg_event ev;
 602  
 603  	ev.type = PKG_EVENT_EXTRACT_BEGIN;
 604  	ev.e_extract_begin.pkg = p;
 605  
 606  	pkg_emit_event(&ev);
 607  }
 608  
 609  void
 610  pkg_emit_extract_finished(struct pkg *p)
 611  {
 612  	struct pkg_event ev;
 613  
 614  	ev.type = PKG_EVENT_EXTRACT_FINISHED;
 615  	ev.e_extract_finished.pkg = p;
 616  
 617  	pkg_emit_event(&ev);
 618  }
 619  
 620  void
 621  pkg_emit_delete_files_begin(struct pkg *p)
 622  {
 623  	struct pkg_event ev;
 624  
 625  	ev.type = PKG_EVENT_DELETE_FILES_BEGIN;
 626  	ev.e_delete_files_begin.pkg = p;
 627  
 628  	pkg_emit_event(&ev);
 629  }
 630  
 631  void
 632  pkg_emit_delete_files_finished(struct pkg *p)
 633  {
 634  	struct pkg_event ev;
 635  
 636  	ev.type = PKG_EVENT_DELETE_FILES_FINISHED;
 637  	ev.e_delete_files_finished.pkg = p;
 638  
 639  	pkg_emit_event(&ev);
 640  }
 641  
 642  void
 643  pkg_emit_integritycheck_begin(void)
 644  {
 645  	struct pkg_event ev;
 646  	ev.type = PKG_EVENT_INTEGRITYCHECK_BEGIN;
 647  
 648  	pkg_emit_event(&ev);
 649  }
 650  
 651  void
 652  pkg_emit_integritycheck_finished(int conflicting)
 653  {
 654  	struct pkg_event ev;
 655  	ev.type = PKG_EVENT_INTEGRITYCHECK_FINISHED;
 656  	ev.e_integrity_finished.conflicting = conflicting;
 657  
 658  	pkg_emit_event(&ev);
 659  }
 660  
 661  void
 662  pkg_emit_integritycheck_conflict(const char *uid,
 663  	const char *path, struct pkg_event_conflict *conflicts)
 664  {
 665  	struct pkg_event ev;
 666  	ev.type = PKG_EVENT_INTEGRITYCHECK_CONFLICT;
 667  	ev.e_integrity_conflict.pkg_uid = uid;
 668  	ev.e_integrity_conflict.pkg_path = path;
 669  	ev.e_integrity_conflict.conflicts = conflicts;
 670  
 671  	pkg_emit_event(&ev);
 672  }
 673  
 674  void
 675  pkg_emit_deinstall_begin(struct pkg *p)
 676  {
 677  	struct pkg_event ev;
 678  
 679  	ev.type = PKG_EVENT_DEINSTALL_BEGIN;
 680  	ev.e_deinstall_begin.pkg = p;
 681  
 682  	pkg_emit_event(&ev);
 683  }
 684  
 685  void
 686  pkg_emit_deinstall_finished(struct pkg *p)
 687  {
 688  	struct pkg_event ev;
 689  	bool syslog_enabled = false;
 690  
 691  	ev.type = PKG_EVENT_DEINSTALL_FINISHED;
 692  	ev.e_deinstall_finished.pkg = p;
 693  
 694  	syslog_enabled = pkg_object_bool(pkg_config_get("SYSLOG"));
 695  	if (syslog_enabled) {
 696  		syslog(LOG_NOTICE, "%s-%s deinstalled",
 697  		    p->name, p->version);
 698  	}
 699  
 700  	pkg_emit_event(&ev);
 701  }
 702  
 703  void
 704  pkg_emit_upgrade_begin(struct pkg *new, struct pkg *old)
 705  {
 706  	struct pkg_event ev;
 707  
 708  	ev.type = PKG_EVENT_UPGRADE_BEGIN;
 709  	ev.e_upgrade_begin.n = new;
 710  	ev.e_upgrade_begin.o = old;
 711  
 712  	pkg_emit_event(&ev);
 713  }
 714  
 715  void
 716  pkg_emit_upgrade_finished(struct pkg *new, struct pkg *old)
 717  {
 718  	struct pkg_event ev;
 719  	bool syslog_enabled = false;
 720  
 721  	ev.type = PKG_EVENT_UPGRADE_FINISHED;
 722  	ev.e_upgrade_finished.n = new;
 723  	ev.e_upgrade_finished.o = old;
 724  
 725  	syslog_enabled = pkg_object_bool(pkg_config_get("SYSLOG"));
 726  	if (syslog_enabled) {
 727  		const char *actions[] = {
 728  			[PKG_DOWNGRADE] = "downgraded",
 729  			[PKG_REINSTALL] = "reinstalled",
 730  			[PKG_UPGRADE]   = "upgraded",
 731  		};
 732  		pkg_change_t action;
 733  
 734  		action = pkg_version_change_between(new, old);
 735  		syslog(LOG_NOTICE, "%s %s: %s %s %s ",
 736  		    new->name, actions[action],
 737  		    old->version != NULL ? old->version : new->version,
 738  		    old->version != NULL ? "->" : "",
 739  		    old->version != NULL ? new->version : "");
 740  	}
 741  
 742  	pkg_emit_event(&ev);
 743  }
 744  
 745  void
 746  pkg_emit_missing_dep(struct pkg *p, struct pkg_dep *d)
 747  {
 748  	struct pkg_event ev;
 749  
 750  	ev.type = PKG_EVENT_MISSING_DEP;
 751  	ev.e_missing_dep.pkg = p;
 752  	ev.e_missing_dep.dep = d;
 753  
 754  	pkg_emit_event(&ev);
 755  }
 756  
 757  void
 758  pkg_emit_locked(struct pkg *p)
 759  {
 760  	struct pkg_event ev;
 761  
 762  	ev.type = PKG_EVENT_LOCKED;
 763  	ev.e_locked.pkg = p;
 764  
 765  	pkg_emit_event(&ev);
 766  }
 767  
 768  void
 769  pkg_emit_required(struct pkg *p, int force)
 770  {
 771  	struct pkg_event ev;
 772  
 773  	ev.type = PKG_EVENT_REQUIRED;
 774  	ev.e_required.pkg = p;
 775  	ev.e_required.force = force;
 776  
 777  	pkg_emit_event(&ev);
 778  }
 779  
 780  void
 781  pkg_emit_nolocaldb(void)
 782  {
 783  	struct pkg_event ev;
 784  	ev.type = PKG_EVENT_NOLOCALDB;
 785  
 786  	pkg_emit_event(&ev);
 787  }
 788  
 789  void
 790  pkg_emit_noremotedb(const char *repo)
 791  {
 792  	struct pkg_event ev;
 793  	ev.type = PKG_EVENT_NOREMOTEDB;
 794  
 795  	ev.e_remotedb.repo = repo;
 796  
 797  	pkg_emit_event(&ev);
 798  }
 799  
 800  void
 801  pkg_emit_newpkgversion(void)
 802  {
 803  	struct pkg_event ev;
 804  	ev.type = PKG_EVENT_NEWPKGVERSION;
 805  
 806  	pkg_emit_event(&ev);
 807  }
 808  
 809  void
 810  pkg_emit_file_mismatch(struct pkg *pkg, struct pkg_file *f, const char *newsum)
 811  {
 812  	struct pkg_event ev;
 813  	ev.type = PKG_EVENT_FILE_MISMATCH;
 814  
 815  	ev.e_file_mismatch.pkg = pkg;
 816  	ev.e_file_mismatch.file = f;
 817  	ev.e_file_mismatch.newsum = newsum;
 818  
 819  	pkg_emit_event(&ev);
 820  }
 821  
 822  void
 823  pkg_emit_file_missing(struct pkg *pkg, struct pkg_file *f)
 824  {
 825  	struct pkg_event ev;
 826  	ev.type = PKG_EVENT_FILE_MISSING;
 827  
 828  	ev.e_file_missing.pkg = pkg;
 829  	ev.e_file_missing.file = f;
 830  
 831  	pkg_emit_event(&ev);
 832  }
 833  
 834  void
 835  pkg_emit_dir_missing(struct pkg *pkg, struct pkg_dir *d)
 836  {
 837  	struct pkg_event ev;
 838  	ev.type = PKG_EVENT_DIR_MISSING;
 839  
 840  	ev.e_dir_missing.pkg = pkg;
 841  	ev.e_dir_missing.dir = d;
 842  
 843  	pkg_emit_event(&ev);
 844  }
 845  
 846  void
 847  pkg_emit_file_meta_mismatch(struct pkg *pkg, struct pkg_file *file,
 848  			    enum pkg_meta_attribute attrib,
 849  			    const char *db_val, const char *fs_val)
 850  {
 851  	struct pkg_event ev;
 852  	ev.type = PKG_EVENT_FILE_META_MISMATCH;
 853  
 854  	ev.e_file_meta_mismatch.pkg = pkg;
 855  	ev.e_file_meta_mismatch.file = file;
 856  	ev.e_file_meta_mismatch.attrib = attrib;
 857  	ev.e_file_meta_mismatch.db_val = db_val;
 858  	ev.e_file_meta_mismatch.fs_val = fs_val;
 859  
 860  	pkg_emit_event(&ev);
 861  }
 862  
 863  void
 864  pkg_emit_dir_meta_mismatch(struct pkg *pkg, struct pkg_dir *dir,
 865  			   enum pkg_meta_attribute attrib,
 866  			   const char *db_val, const char *fs_val)
 867  {
 868  	struct pkg_event ev;
 869  	ev.type = PKG_EVENT_DIR_META_MISMATCH;
 870  
 871  	ev.e_dir_meta_mismatch.pkg = pkg;
 872  	ev.e_dir_meta_mismatch.dir = dir;
 873  	ev.e_dir_meta_mismatch.attrib = attrib;
 874  	ev.e_dir_meta_mismatch.db_val = db_val;
 875  	ev.e_dir_meta_mismatch.fs_val = fs_val;
 876  
 877  	pkg_emit_event(&ev);
 878  }
 879  
 880  void
 881  pkg_emit_file_meta_ok(struct pkg *pkg, struct pkg_file *file)
 882  {
 883  	struct pkg_event ev;
 884  	ev.type = PKG_EVENT_FILE_META_OK;
 885  
 886  	ev.e_file_ok.pkg = pkg;
 887  	ev.e_file_ok.file = file;
 888  
 889  	pkg_emit_event(&ev);
 890  }
 891  
 892  void
 893  pkg_emit_dir_meta_ok(struct pkg *pkg, struct pkg_dir *dir)
 894  {
 895  	struct pkg_event ev;
 896  	ev.type = PKG_EVENT_DIR_META_OK;
 897  
 898  	ev.e_dir_ok.pkg = pkg;
 899  	ev.e_dir_ok.dir = dir;
 900  
 901  	pkg_emit_event(&ev);
 902  }
 903  
 904  void
 905  pkg_plugin_errno(struct pkg_plugin *p, const char *func, const char *arg)
 906  {
 907  	struct pkg_event ev;
 908  
 909  	ev.type = PKG_EVENT_PLUGIN_ERRNO;
 910  	ev.e_plugin_errno.plugin = p;
 911  	ev.e_plugin_errno.func = func;
 912  	ev.e_plugin_errno.arg = arg;
 913  	ev.e_plugin_errno.no = errno;
 914  
 915  	pkg_emit_event(&ev);
 916  }
 917  
 918  void
 919  pkg_plugin_error(struct pkg_plugin *p, const char *fmt, ...)
 920  {
 921  	struct pkg_event ev;
 922  	va_list ap;
 923  
 924  	ev.type = PKG_EVENT_PLUGIN_ERROR;
 925  	ev.e_plugin_error.plugin = p;
 926  
 927  	va_start(ap, fmt);
 928  	vasprintf(&ev.e_plugin_error.msg, fmt, ap);
 929  	va_end(ap);
 930  
 931  	pkg_emit_event(&ev);
 932  	free(ev.e_plugin_error.msg);
 933  }
 934  
 935  void
 936  pkg_plugin_info(struct pkg_plugin *p, const char *fmt, ...)
 937  {
 938  	struct pkg_event ev;
 939  	va_list ap;
 940  
 941  	ev.type = PKG_EVENT_PLUGIN_INFO;
 942  	ev.e_plugin_info.plugin = p;
 943  
 944  	va_start(ap, fmt);
 945  	vasprintf(&ev.e_plugin_info.msg, fmt, ap);
 946  	va_end(ap);
 947  
 948  	pkg_emit_event(&ev);
 949  	free(ev.e_plugin_info.msg);
 950  }
 951  
 952  void
 953  pkg_emit_package_not_found(const char *p)
 954  {
 955  	struct pkg_event ev;
 956  
 957  	ev.type = PKG_EVENT_NOT_FOUND;
 958  	ev.e_not_found.pkg_name = p;
 959  
 960  	pkg_emit_event(&ev);
 961  }
 962  
 963  void
 964  pkg_emit_incremental_update_begin(const char *reponame)
 965  {
 966  	struct pkg_event ev;
 967  
 968  	ev.type = PKG_EVENT_INCREMENTAL_UPDATE_BEGIN;
 969  	ev.e_incremental_update.reponame = reponame;
 970  	ev.e_incremental_update.processed = 0;
 971  
 972  	pkg_emit_event(&ev);
 973  }
 974  
 975  void
 976  pkg_emit_incremental_update(const char *reponame, int processed)
 977  {
 978  	struct pkg_event ev;
 979  
 980  	ev.type = PKG_EVENT_INCREMENTAL_UPDATE;
 981  	ev.e_incremental_update.reponame = reponame;
 982  	ev.e_incremental_update.processed = processed;
 983  
 984  	pkg_emit_event(&ev);
 985  }
 986  
 987  bool
 988  pkg_emit_query_yesno(bool deft, const char *msg)
 989  {
 990  	struct pkg_event ev;
 991  	int ret;
 992  
 993  	ev.type = PKG_EVENT_QUERY_YESNO;
 994  	ev.e_query_yesno.msg = msg;
 995  	ev.e_query_yesno.deft = deft;
 996  
 997  	ret = pkg_emit_event(&ev);
 998  	return (ret ? true : false);
 999  }
1000  
1001  int
1002  pkg_emit_query_select(const char *msg, const char **items, int ncnt, int deft)
1003  {
1004  	struct pkg_event ev;
1005  	int ret;
1006  
1007  	ev.type = PKG_EVENT_QUERY_SELECT;
1008  	ev.e_query_select.msg = msg;
1009  	ev.e_query_select.items = items;
1010  	ev.e_query_select.ncnt = ncnt;
1011  	ev.e_query_select.deft = deft;
1012  
1013  	ret = pkg_emit_event(&ev);
1014  	return ret;
1015  }
1016  
1017  int
1018  pkg_emit_sandbox_get_string(pkg_sandbox_cb call, void *ud, char **str, int64_t *len)
1019  {
1020  	struct pkg_event ev;
1021  
1022  	if (_cb == NULL)
1023  		return (pkg_handle_sandboxed_get_string(call, str, len, ud));
1024  
1025  	ev.type = PKG_EVENT_SANDBOX_GET_STRING;
1026  	ev.e_sandbox_call_str.call = call;
1027  	ev.e_sandbox_call_str.userdata = ud;
1028  	ev.e_sandbox_call_str.result = str;
1029  	ev.e_sandbox_call_str.len = len;
1030  
1031  	return (pkg_emit_event(&ev));
1032  }
1033  
1034  int
1035  pkg_emit_sandbox_call(pkg_sandbox_cb call, int fd, void *ud)
1036  {
1037  	struct pkg_event ev;
1038  
1039  	if (_cb == NULL)
1040  		return (pkg_handle_sandboxed_call(call, fd, ud));
1041  
1042  	ev.type = PKG_EVENT_SANDBOX_CALL;
1043  	ev.e_sandbox_call.call = call;
1044  	ev.e_sandbox_call.fd = fd;
1045  	ev.e_sandbox_call.userdata = ud;
1046  
1047  	return (pkg_emit_event(&ev));
1048  }
1049  
1050  void
1051  pkg_debug(int level, const char *fmt, ...)
1052  {
1053  	struct pkg_event ev;
1054  	va_list ap;
1055  
1056  	if (ctx.debug_level < level)
1057  		return;
1058  
1059  	ev.type = PKG_EVENT_DEBUG;
1060  	ev.e_debug.level = level;
1061  	va_start(ap, fmt);
1062  	vasprintf(&ev.e_debug.msg, fmt, ap);
1063  	va_end(ap);
1064  
1065  	pkg_emit_event(&ev);
1066  	free(ev.e_debug.msg);
1067  }
1068  
1069  void
1070  pkg_dbg(uint64_t flags, int level, const char *fmt, ...)
1071  {
1072  	struct pkg_event ev;
1073  	va_list ap;
1074  	xstring *string_fmt;
1075  	char *nfmt;
1076  
1077  	if (ctx.debug_level < level)
1078  		return;
1079  
1080  	if ((ctx.debug_flags & (flags|PKG_DBG_ALL)) == 0)
1081  		return;
1082  
1083  	string_fmt = xstring_new();
1084  	ev.type = PKG_EVENT_DEBUG;
1085  	ev.e_debug.level = level;
1086  	for (size_t i = 0; i < NELEM(debug_flags); i++) {
1087  		if (flags & debug_flags[i].flag) {
1088  			if (string_fmt->size == 0) {
1089  				fprintf(string_fmt->fp, "(%s", debug_flags[i].name);
1090  				fflush(string_fmt->fp);
1091  			} else {
1092  				fprintf(string_fmt->fp, "|%s", debug_flags[i].name);
1093  			}
1094  		}
1095  	}
1096  	fprintf(string_fmt->fp, ") %s", fmt);
1097  	nfmt = xstring_get(string_fmt);
1098  	va_start(ap, fmt);
1099  	vasprintf(&ev.e_debug.msg, nfmt, ap);
1100  	va_end(ap);
1101  
1102  	pkg_emit_event(&ev);
1103  	free(ev.e_debug.msg);
1104  	free(nfmt);
1105  }
1106  
1107  
1108  void
1109  pkg_emit_backup(void)
1110  {
1111  	struct pkg_event ev;
1112  
1113  	ev.type = PKG_EVENT_BACKUP;
1114  
1115  	pkg_emit_event(&ev);
1116  }
1117  
1118  void
1119  pkg_emit_restore(void)
1120  {
1121  	struct pkg_event ev;
1122  
1123  	ev.type = PKG_EVENT_RESTORE;
1124  
1125  	pkg_emit_event(&ev);
1126  }
1127  
1128  void
1129  pkg_emit_progress_start(const char *fmt, ...)
1130  {
1131  	struct pkg_event ev;
1132  	va_list ap;
1133  
1134  	ev.type = PKG_EVENT_PROGRESS_START;
1135  	if (fmt != NULL) {
1136  		va_start(ap, fmt);
1137  		vasprintf(&ev.e_progress_start.msg, fmt, ap);
1138  		va_end(ap);
1139  	} else {
1140  		ev.e_progress_start.msg = NULL;
1141  	}
1142  
1143  	pkg_emit_event(&ev);
1144  	free(ev.e_progress_start.msg);
1145  }
1146  
1147  int
1148  pkg_emit_progress_tick(int64_t current, int64_t total)
1149  {
1150  	struct pkg_event ev;
1151  
1152  	ev.type = PKG_EVENT_PROGRESS_TICK;
1153  	ev.e_progress_tick.current = current;
1154  	ev.e_progress_tick.total = total;
1155  
1156  	return !!pkg_emit_event(&ev);
1157  }
1158  
1159  void
1160  pkg_emit_new_action(size_t current, size_t total)
1161  {
1162  	struct pkg_event ev;
1163  
1164  	ev.type = PKG_EVENT_NEW_ACTION;
1165  	ev.e_action.total = total;
1166  	ev.e_action.current = current;
1167  
1168  	pkg_emit_event(&ev);
1169  }
1170  
1171  void
1172  pkg_emit_message(const char *message)
1173  {
1174  	struct pkg_event ev;
1175  
1176  	ev.type = PKG_EVENT_MESSAGE;
1177  	ev.e_pkg_message.msg = message;
1178  	pkg_emit_event(&ev);
1179  }
1180  
1181  void
1182  pkg_register_cleanup_callback(void (*cleanup_cb)(void *data), void *data)
1183  {
1184  	struct pkg_event ev;
1185  
1186  	ev.type = PKG_EVENT_CLEANUP_CALLBACK_REGISTER;
1187  	ev.e_cleanup_callback.cleanup_cb = cleanup_cb;
1188  	ev.e_cleanup_callback.data = data;
1189  	pkg_emit_event(&ev);
1190  }
1191  
1192  void
1193  pkg_unregister_cleanup_callback(void (*cleanup_cb)(void *data), void *data)
1194  {
1195  	struct pkg_event ev;
1196  
1197  	ev.type = PKG_EVENT_CLEANUP_CALLBACK_UNREGISTER;
1198  	ev.e_cleanup_callback.cleanup_cb = cleanup_cb;
1199  	ev.e_cleanup_callback.data = data;
1200  	pkg_emit_event(&ev);
1201  }
1202  
1203  void
1204  pkg_emit_conflicts(struct pkg *p1, struct pkg *p2, const char *path)
1205  {
1206  	struct pkg_event ev;
1207  
1208  	ev.type = PKG_EVENT_CONFLICTS;
1209  	ev.e_conflicts.p1 = p1;
1210  	ev.e_conflicts.p2 = p2;
1211  	ev.e_conflicts.path = path;
1212  	pkg_emit_event(&ev);
1213  }
1214  
1215  void
1216  pkg_emit_triggers_begin(void)
1217  {
1218  	struct pkg_event ev;
1219  
1220  	ev.type = PKG_EVENT_TRIGGERS_BEGIN;
1221  
1222  	pkg_emit_event(&ev);
1223  }
1224  
1225  void
1226  pkg_emit_triggers_finished(void)
1227  {
1228  	struct pkg_event ev;
1229  
1230  	ev.type = PKG_EVENT_TRIGGERS_FINISHED;
1231  
1232  	pkg_emit_event(&ev);
1233  }
1234  
1235  void
1236  pkg_emit_trigger(const char *name, bool cleanup)
1237  {
1238  	struct pkg_event ev;
1239  
1240  	ev.type = PKG_EVENT_TRIGGER;
1241  	ev.e_trigger.name = name;
1242  	ev.e_trigger.cleanup = cleanup;
1243  
1244  	pkg_emit_event(&ev);
1245  }