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