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