Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/src/event.c
2065 views
1
/*-
2
* Copyright (c) 2011-2014 Baptiste Daroussin <[email protected]>
3
* Copyright (c) 2011-2012 Julien Laffaye <[email protected]>
4
* Copyright (c) 2011 Will Andrews <[email protected]>
5
* Copyright (c) 2011-2012 Marin Atanasov Nikolov <[email protected]>
6
* Copyright (c) 2014 Vsevolod Stakhov <[email protected]>
7
* Copyright (c) 2015 Matthew Seaman <[email protected]>
8
* All rights reserved.
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer
15
* in this position and unchanged.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
21
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
24
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32
#ifdef HAVE_CONFIG_H
33
#include "pkg_config.h"
34
#endif
35
36
#include <sys/resource.h>
37
#include <sys/types.h>
38
#ifdef HAVE_LIBJAIL
39
#include <sys/sysctl.h>
40
#endif
41
#include <sys/wait.h>
42
#include <sys/socket.h>
43
44
#ifdef HAVE_CAPSICUM
45
#include <sys/capsicum.h>
46
#endif
47
48
#include <err.h>
49
#include <string.h>
50
#include <unistd.h>
51
#include <errno.h>
52
#include <time.h>
53
#include <signal.h>
54
#ifdef HAVE_LIBUTIL_H
55
#include <libutil.h>
56
#endif
57
58
#include <bsd_compat.h>
59
60
#include "pkg.h"
61
#include "pkgcli.h"
62
#include "xmalloc.h"
63
64
#define STALL_TIME 5
65
66
xstring *messages = NULL;
67
xstring *conflicts = NULL;
68
69
struct cleanup {
70
void *data;
71
void (*cb)(void *);
72
};
73
74
static char *progress_message = NULL;
75
static xstring *msg_buf = NULL;
76
static int last_progress_percent = -1;
77
static bool progress_started = false;
78
static bool progress_interrupted = false;
79
static bool progress_debit = false;
80
static int64_t last_tick = 0;
81
static int64_t stalled;
82
static int64_t bytes_per_second;
83
static time_t last_update;
84
static time_t begin = 0;
85
static int add_deps_depth;
86
static vec_t(struct cleanup *) cleanup_list = vec_init();
87
static bool signal_handler_installed = false;
88
static size_t nbactions = 0;
89
static size_t nbdone = 0;
90
91
/* units for format_size */
92
static const char *unit_SI[] = { " ", "k", "M", "G", "T", };
93
94
static void draw_progressbar(int64_t current, int64_t total);
95
96
static void
97
cleanup_handler(int dummy __unused)
98
{
99
struct cleanup *ev;
100
101
if (cleanup_list.len == 0)
102
return;
103
warnx("\nsignal received, cleaning up");
104
vec_foreach(cleanup_list, i) {
105
ev = cleanup_list.d[i];
106
ev->cb(ev->data);
107
}
108
exit(1);
109
}
110
111
static void
112
format_rate_SI(char *buf, int size, off_t bytes)
113
{
114
int i;
115
116
bytes *= 100;
117
for (i = 0; bytes >= 100*1000 && unit_SI[i][0] != 'T'; i++)
118
bytes = (bytes + 500) / 1000;
119
if (i == 0) {
120
i++;
121
bytes = (bytes + 500) / 1000;
122
}
123
snprintf(buf, size, "%3lld.%1lld%sB",
124
(long long) (bytes + 5) / 100,
125
(long long) (bytes + 5) / 10 % 10,
126
unit_SI[i]);
127
}
128
129
void
130
job_status_end(xstring *msg)
131
{
132
fflush(msg->fp);
133
printf("%s\n", msg->buf);
134
xstring_reset(msg);
135
}
136
137
void
138
job_status_begin(xstring *msg)
139
{
140
int n;
141
142
xstring_reset(msg);
143
#ifdef HAVE_LIBJAIL
144
static char hostname[MAXHOSTNAMELEN] = "";
145
static int jailed = -1;
146
size_t intlen;
147
148
if (jailed == -1) {
149
intlen = sizeof(jailed);
150
if (sysctlbyname("security.jail.jailed", &jailed, &intlen,
151
NULL, 0) == -1)
152
jailed = 0;
153
}
154
155
if (jailed == 1) {
156
if (hostname[0] == '\0')
157
gethostname(hostname, sizeof(hostname));
158
159
fprintf(msg->fp, "[%s] ", hostname);
160
}
161
#endif
162
163
/* Only used for pkg-add right now. */
164
if (add_deps_depth) {
165
if (add_deps_depth > 1) {
166
for (n = 0; n < (2 * add_deps_depth); ++n) {
167
if (n % 4 == 0 && n < (2 * add_deps_depth))
168
fprintf(msg->fp, "|");
169
else
170
fprintf(msg->fp, " ");
171
}
172
}
173
fprintf(msg->fp, "`-- ");
174
}
175
176
if ((nbtodl > 0 || nbactions > 0) && nbdone > 0)
177
fprintf(msg->fp, "[%zu/%zu] ", nbdone, (nbtodl) ? nbtodl : nbactions);
178
if (nbtodl > 0 && nbtodl == nbdone) {
179
nbtodl = 0;
180
nbdone = 0;
181
}
182
}
183
184
void
185
progressbar_start(const char *pmsg)
186
{
187
if (progress_message) {
188
free(progress_message);
189
progress_message = NULL;
190
}
191
192
if (quiet)
193
return;
194
if (pmsg != NULL)
195
progress_message = xstrdup(pmsg);
196
else {
197
fflush(msg_buf->fp);
198
progress_message = xstrdup(msg_buf->buf);
199
}
200
last_progress_percent = -1;
201
last_tick = 0;
202
begin = last_update = time(NULL);
203
bytes_per_second = 0;
204
stalled = 0;
205
206
progress_started = true;
207
progress_interrupted = false;
208
if (!isatty(STDOUT_FILENO))
209
printf("%s: ", progress_message);
210
else
211
printf("%s: 0%%", progress_message);
212
}
213
214
void
215
progressbar_tick(int64_t current, int64_t total)
216
{
217
int percent;
218
219
if (!quiet && progress_started) {
220
if (isatty(STDOUT_FILENO))
221
draw_progressbar(current, total);
222
else {
223
if (progress_interrupted) {
224
printf("%s...", progress_message);
225
} else if (!getenv("NO_TICK")){
226
percent = (total != 0) ? (current * 100. / total) : 100;
227
if (last_progress_percent / 10 < percent / 10) {
228
last_progress_percent = percent;
229
putchar('.');
230
fflush(stdout);
231
}
232
}
233
if (current >= total)
234
progressbar_stop();
235
}
236
}
237
progress_interrupted = false;
238
}
239
240
void
241
progressbar_stop(void)
242
{
243
if (progress_started) {
244
if (!isatty(STDOUT_FILENO))
245
printf(" done");
246
putchar('\n');
247
}
248
last_progress_percent = -1;
249
progress_started = false;
250
progress_interrupted = false;
251
}
252
253
static void
254
draw_progressbar(int64_t current, int64_t total)
255
{
256
int percent;
257
int64_t transferred;
258
time_t elapsed = 0, now = 0;
259
char buf[8];
260
int64_t bytes_left;
261
int cur_speed;
262
int hours, minutes, seconds;
263
float age_factor;
264
265
if (!progress_started) {
266
progressbar_stop();
267
return;
268
}
269
270
if (progress_debit) {
271
now = time(NULL);
272
elapsed = (now >= last_update) ? now - last_update : 0;
273
}
274
275
percent = (total != 0) ? (current * 100. / total) : 100;
276
277
/**
278
* Wait for interval for debit bars to keep calc per second.
279
* If not debit, show on every % change, or if ticking after
280
* an interruption (which removed our progressbar output).
281
*/
282
if (current >= total || (progress_debit && elapsed >= 1) ||
283
(!progress_debit &&
284
(percent != last_progress_percent || progress_interrupted))) {
285
last_progress_percent = percent;
286
287
printf("\r%s: %3d%%", progress_message, percent);
288
if (progress_debit) {
289
transferred = current - last_tick;
290
last_tick = current;
291
bytes_left = total - current;
292
if (bytes_left <= 0) {
293
elapsed = now - begin;
294
/* Always show at least 1 second at end. */
295
if (elapsed == 0)
296
elapsed = 1;
297
/* Calculate true total speed when done */
298
transferred = total;
299
bytes_per_second = 0;
300
}
301
302
if (elapsed != 0)
303
cur_speed = (transferred / elapsed);
304
else
305
cur_speed = transferred;
306
307
#define AGE_FACTOR_SLOW_START 3
308
if (now - begin <= AGE_FACTOR_SLOW_START)
309
age_factor = 0.4;
310
else
311
age_factor = 0.9;
312
313
if (bytes_per_second != 0) {
314
bytes_per_second =
315
(bytes_per_second * age_factor) +
316
(cur_speed * (1.0 - age_factor));
317
} else
318
bytes_per_second = cur_speed;
319
320
humanize_number(buf, sizeof(buf),
321
current,"B", HN_AUTOSCALE, HN_IEC_PREFIXES);
322
printf(" %*s", (int)sizeof(buf), buf);
323
324
if (bytes_left > 0)
325
format_rate_SI(buf, sizeof(buf), transferred);
326
else /* Show overall speed when done */
327
format_rate_SI(buf, sizeof(buf),
328
bytes_per_second);
329
printf(" %s/s ", buf);
330
331
if (!transferred)
332
stalled += elapsed;
333
else
334
stalled = 0;
335
336
if (stalled >= STALL_TIME)
337
printf(" - stalled -");
338
else if (bytes_per_second == 0 && bytes_left > 0)
339
printf(" --:-- ETA");
340
else {
341
if (bytes_left > 0)
342
seconds = bytes_left / bytes_per_second;
343
else
344
seconds = elapsed;
345
346
hours = seconds / 3600;
347
seconds -= hours * 3600;
348
minutes = seconds / 60;
349
seconds -= minutes * 60;
350
351
if (hours != 0)
352
printf("%02d:%02d:%02d", hours,
353
minutes, seconds);
354
else
355
printf(" %02d:%02d", minutes, seconds);
356
357
if (bytes_left > 0)
358
printf(" ETA");
359
else
360
printf(" ");
361
}
362
last_update = now;
363
}
364
fflush(stdout);
365
}
366
if (current >= total)
367
progressbar_stop();
368
}
369
370
int
371
event_callback(void *data, struct pkg_event *ev)
372
{
373
struct pkg *pkg = NULL, *pkg_new, *pkg_old;
374
struct cleanup *evtmp;
375
int *debug = data;
376
struct pkg_event_conflict *cur_conflict;
377
const char *filename, *reponame = NULL;
378
379
if (msg_buf == NULL) {
380
msg_buf = xstring_new();
381
}
382
383
/*
384
* If a progressbar has been interrupted by another event, then
385
* we need to add a newline to prevent bad formatting.
386
*/
387
if (progress_started && ev->type != PKG_EVENT_PROGRESS_TICK &&
388
!progress_interrupted) {
389
putchar('\n');
390
progress_interrupted = true;
391
}
392
393
switch(ev->type) {
394
case PKG_EVENT_ERRNO:
395
warnx("%s(%s): %s", ev->e_errno.func, ev->e_errno.arg,
396
strerror(ev->e_errno.no));
397
break;
398
case PKG_EVENT_ERROR:
399
warnx("%s", ev->e_pkg_error.msg);
400
break;
401
case PKG_EVENT_NOTICE:
402
if (!quiet)
403
printf("%s\n", ev->e_pkg_notice.msg);
404
break;
405
case PKG_EVENT_DEVELOPER_MODE:
406
warnx("DEVELOPER_MODE: %s", ev->e_pkg_error.msg);
407
break;
408
case PKG_EVENT_UPDATE_ADD:
409
if (quiet || !isatty(STDOUT_FILENO))
410
break;
411
printf("\rPushing new entries %d/%d", ev->e_upd_add.done, ev->e_upd_add.total);
412
if (ev->e_upd_add.total == ev->e_upd_add.done)
413
putchar('\n');
414
break;
415
case PKG_EVENT_UPDATE_REMOVE:
416
if (quiet || !isatty(STDOUT_FILENO))
417
break;
418
printf("\rRemoving entries %d/%d", ev->e_upd_remove.done, ev->e_upd_remove.total);
419
if (ev->e_upd_remove.total == ev->e_upd_remove.done)
420
putchar('\n');
421
break;
422
case PKG_EVENT_FETCH_BEGIN:
423
if (nbtodl > 0)
424
nbdone++;
425
if (quiet)
426
break;
427
filename = strrchr(ev->e_fetching.url, '/');
428
if (filename != NULL) {
429
filename++;
430
} else {
431
/*
432
* We failed at being smart, so display
433
* the entire url.
434
*/
435
filename = ev->e_fetching.url;
436
}
437
job_status_begin(msg_buf);
438
progress_debit = true;
439
fprintf(msg_buf->fp, "Fetching %s", filename);
440
break;
441
case PKG_EVENT_FETCH_FINISHED:
442
progress_debit = false;
443
break;
444
case PKG_EVENT_INSTALL_BEGIN:
445
if (quiet)
446
break;
447
job_status_begin(msg_buf);
448
449
pkg = ev->e_install_begin.pkg;
450
pkg_fprintf(msg_buf->fp, "Installing %n-%v...\n", pkg,
451
pkg);
452
fflush(msg_buf->fp);
453
printf("%s", msg_buf->buf);
454
break;
455
case PKG_EVENT_INSTALL_FINISHED:
456
if (quiet)
457
break;
458
break;
459
case PKG_EVENT_EXTRACT_BEGIN:
460
if (quiet)
461
break;
462
else {
463
job_status_begin(msg_buf);
464
pkg = ev->e_install_begin.pkg;
465
pkg_fprintf(msg_buf->fp, "Extracting %n-%v", pkg, pkg);
466
fflush(msg_buf->fp);
467
}
468
break;
469
case PKG_EVENT_EXTRACT_FINISHED:
470
break;
471
case PKG_EVENT_ADD_DEPS_BEGIN:
472
++add_deps_depth;
473
break;
474
case PKG_EVENT_ADD_DEPS_FINISHED:
475
--add_deps_depth;
476
break;
477
case PKG_EVENT_INTEGRITYCHECK_BEGIN:
478
if (quiet)
479
break;
480
printf("Checking integrity...");
481
break;
482
case PKG_EVENT_INTEGRITYCHECK_FINISHED:
483
if (quiet)
484
break;
485
printf(" done (%d conflicting)\n", ev->e_integrity_finished.conflicting);
486
if (conflicts != NULL) {
487
fflush(conflicts->fp);
488
printf("%s", conflicts->buf);
489
xstring_free(conflicts);
490
conflicts = NULL;
491
}
492
break;
493
case PKG_EVENT_INTEGRITYCHECK_CONFLICT:
494
if (*debug == 0)
495
break;
496
printf("\nConflict found on path %s between %s and ",
497
ev->e_integrity_conflict.pkg_path,
498
ev->e_integrity_conflict.pkg_uid);
499
cur_conflict = ev->e_integrity_conflict.conflicts;
500
while (cur_conflict) {
501
if (cur_conflict->next)
502
printf("%s, ", cur_conflict->uid);
503
else
504
printf("%s", cur_conflict->uid);
505
506
cur_conflict = cur_conflict->next;
507
}
508
printf("\n");
509
break;
510
case PKG_EVENT_DEINSTALL_BEGIN:
511
if (quiet)
512
break;
513
514
job_status_begin(msg_buf);
515
516
pkg = ev->e_install_begin.pkg;
517
pkg_fprintf(msg_buf->fp, "Deinstalling %n-%v...\n", pkg, pkg);
518
fflush(msg_buf->fp);
519
printf("%s", msg_buf->buf);
520
break;
521
case PKG_EVENT_DEINSTALL_FINISHED:
522
if (quiet)
523
break;
524
break;
525
case PKG_EVENT_DELETE_FILES_BEGIN:
526
if (quiet)
527
break;
528
else {
529
job_status_begin(msg_buf);
530
pkg = ev->e_install_begin.pkg;
531
pkg_fprintf(msg_buf->fp, "Deleting files for %n-%v",
532
pkg, pkg);
533
}
534
break;
535
case PKG_EVENT_DELETE_FILES_FINISHED:
536
break;
537
case PKG_EVENT_UPGRADE_BEGIN:
538
if (quiet)
539
break;
540
pkg_new = ev->e_upgrade_begin.n;
541
pkg_old = ev->e_upgrade_begin.o;
542
543
job_status_begin(msg_buf);
544
545
switch (pkg_version_change_between(pkg_new, pkg_old)) {
546
case PKG_DOWNGRADE:
547
pkg_fprintf(msg_buf->fp, "Downgrading %n from %v to %v...\n",
548
pkg_new, pkg_old, pkg_new);
549
break;
550
case PKG_REINSTALL:
551
pkg_fprintf(msg_buf->fp, "Reinstalling %n-%v...\n",
552
pkg_old, pkg_old);
553
break;
554
case PKG_UPGRADE:
555
pkg_fprintf(msg_buf->fp, "Upgrading %n from %v to %v...\n",
556
pkg_new, pkg_old, pkg_new);
557
break;
558
}
559
fflush(msg_buf->fp);
560
printf("%s", msg_buf->buf);
561
break;
562
case PKG_EVENT_UPGRADE_FINISHED:
563
if (quiet)
564
break;
565
break;
566
case PKG_EVENT_LOCKED:
567
pkg = ev->e_locked.pkg;
568
pkg_printf("\n%n-%v is locked and may not be modified\n", pkg, pkg);
569
break;
570
case PKG_EVENT_REQUIRED:
571
pkg = ev->e_required.pkg;
572
pkg_printf("\n%n-%v is required by: %r%{%rn-%rv%| %}", pkg, pkg, pkg);
573
if (ev->e_required.force == 1)
574
fprintf(stderr, ", deleting anyway\n");
575
else
576
fprintf(stderr, "\n");
577
break;
578
case PKG_EVENT_ALREADY_INSTALLED:
579
if (quiet)
580
break;
581
pkg = ev->e_already_installed.pkg;
582
pkg_printf("the most recent version of %n-%v is already installed\n",
583
pkg, pkg);
584
break;
585
case PKG_EVENT_NOT_FOUND:
586
printf("Package '%s' was not found in "
587
"the repositories\n", ev->e_not_found.pkg_name);
588
break;
589
case PKG_EVENT_MISSING_DEP:
590
warnx("Missing dependency '%s'",
591
pkg_dep_name(ev->e_missing_dep.dep));
592
break;
593
case PKG_EVENT_NOREMOTEDB:
594
fprintf(stderr, "Unable to open remote database \"%s\". "
595
"Try running '%s update' first.\n", ev->e_remotedb.repo,
596
getprogname());
597
break;
598
case PKG_EVENT_NOLOCALDB:
599
fprintf(stderr, "Local package database nonexistent!\n");
600
break;
601
case PKG_EVENT_NEWPKGVERSION:
602
newpkgversion = true;
603
printf("New version of pkg detected; it needs to be "
604
"installed first.\n");
605
break;
606
case PKG_EVENT_FILE_MISMATCH:
607
pkg = ev->e_file_mismatch.pkg;
608
pkg_fprintf(stderr, "%n-%v: checksum mismatch for %Fn\n", pkg,
609
pkg, ev->e_file_mismatch.file);
610
break;
611
case PKG_EVENT_FILE_MISSING:
612
pkg = ev->e_file_missing.pkg;
613
pkg_fprintf(stderr, "%n-%v: missing file %Fn\n", pkg, pkg,
614
ev->e_file_missing.file);
615
break;
616
case PKG_EVENT_PLUGIN_ERRNO:
617
warnx("%s: %s(%s): %s",
618
pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME),
619
ev->e_plugin_errno.func, ev->e_plugin_errno.arg,
620
strerror(ev->e_plugin_errno.no));
621
break;
622
case PKG_EVENT_PLUGIN_ERROR:
623
warnx("%s: %s",
624
pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME),
625
ev->e_plugin_error.msg);
626
break;
627
case PKG_EVENT_PLUGIN_INFO:
628
if (quiet)
629
break;
630
printf("%s: %s\n",
631
pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME),
632
ev->e_plugin_info.msg);
633
break;
634
case PKG_EVENT_INCREMENTAL_UPDATE:
635
if (!quiet)
636
printf("%s repository update completed. %d packages processed.\n",
637
ev->e_incremental_update.reponame,
638
ev->e_incremental_update.processed);
639
break;
640
case PKG_EVENT_DEBUG:
641
fprintf(stderr, "DBG(%d)[%d]> %s\n", ev->e_debug.level,
642
(int)getpid(), ev->e_debug.msg);
643
break;
644
case PKG_EVENT_QUERY_YESNO:
645
return ( ev->e_query_yesno.deft ?
646
query_yesno(true, ev->e_query_yesno.msg, "[Y/n]") :
647
query_yesno(false, ev->e_query_yesno.msg, "[y/N]") );
648
break;
649
case PKG_EVENT_QUERY_SELECT:
650
return query_select(ev->e_query_select.msg, ev->e_query_select.items,
651
ev->e_query_select.ncnt, ev->e_query_select.deft);
652
break;
653
case PKG_EVENT_SANDBOX_CALL:
654
return ( pkg_handle_sandboxed_call(ev->e_sandbox_call.call,
655
ev->e_sandbox_call.fd,
656
ev->e_sandbox_call.userdata) );
657
break;
658
case PKG_EVENT_SANDBOX_GET_STRING:
659
return ( pkg_handle_sandboxed_get_string(ev->e_sandbox_call_str.call,
660
ev->e_sandbox_call_str.result,
661
ev->e_sandbox_call_str.len,
662
ev->e_sandbox_call_str.userdata) );
663
break;
664
case PKG_EVENT_PROGRESS_START:
665
progressbar_start(ev->e_progress_start.msg);
666
break;
667
case PKG_EVENT_PROGRESS_TICK:
668
progressbar_tick(ev->e_progress_tick.current,
669
ev->e_progress_tick.total);
670
break;
671
case PKG_EVENT_BACKUP:
672
fprintf(msg_buf->fp, "Backing up");
673
break;
674
case PKG_EVENT_RESTORE:
675
fprintf(msg_buf->fp, "Restoring");
676
break;
677
case PKG_EVENT_NEW_ACTION:
678
nbactions = ev->e_action.total;
679
nbdone = ev->e_action.current;
680
break;
681
case PKG_EVENT_MESSAGE:
682
if (messages == NULL)
683
messages = xstring_new();
684
fprintf(messages->fp, "%s", ev->e_pkg_message.msg);
685
break;
686
case PKG_EVENT_CLEANUP_CALLBACK_REGISTER:
687
if (!signal_handler_installed) {
688
signal(SIGINT, cleanup_handler);
689
signal_handler_installed = true;
690
}
691
evtmp = xmalloc(sizeof(struct cleanup));
692
evtmp->cb = ev->e_cleanup_callback.cleanup_cb;
693
evtmp->data = ev->e_cleanup_callback.data;
694
vec_push(&cleanup_list, evtmp);
695
break;
696
case PKG_EVENT_CLEANUP_CALLBACK_UNREGISTER:
697
if (!signal_handler_installed)
698
break;
699
vec_foreach(cleanup_list, i) {
700
evtmp = cleanup_list.d[i];
701
if (evtmp->cb == ev->e_cleanup_callback.cleanup_cb &&
702
evtmp->data == ev->e_cleanup_callback.data) {
703
vec_remove_and_free(&cleanup_list, i, free);
704
break;
705
}
706
}
707
break;
708
case PKG_EVENT_CONFLICTS:
709
if (conflicts == NULL) {
710
conflicts = xstring_new();
711
}
712
pkg_fprintf(conflicts->fp, " - %n-%v",
713
ev->e_conflicts.p1, ev->e_conflicts.p1);
714
if (pkg_repos_total_count() > 1) {
715
pkg_get(ev->e_conflicts.p1, PKG_ATTR_REPONAME, &reponame);
716
fprintf(conflicts->fp, " [%s]",
717
reponame == NULL ? "installed" : reponame);
718
}
719
pkg_fprintf(conflicts->fp, " conflicts with %n-%v",
720
ev->e_conflicts.p2, ev->e_conflicts.p2);
721
if (pkg_repos_total_count() > 1) {
722
pkg_get(ev->e_conflicts.p2, PKG_ATTR_REPONAME, &reponame);
723
fprintf(conflicts->fp, " [%s]",
724
reponame == NULL ? "installed" : reponame);
725
}
726
fprintf(conflicts->fp, " on %s\n",
727
ev->e_conflicts.path);
728
break;
729
case PKG_EVENT_TRIGGER:
730
if (!quiet) {
731
if (ev->e_trigger.cleanup)
732
printf("==> Cleaning up trigger: %s\n", ev->e_trigger.name);
733
else
734
printf("==> Running trigger: %s\n", ev->e_trigger.name);
735
}
736
default:
737
break;
738
}
739
740
return 0;
741
}
742
743