xref: /openbsd-src/usr.sbin/pkg_add/OpenBSD/AddDelete.pm (revision 9cb26fd53e9c5600c2f38ca940e1c400d9a2516e)
1f76cebffSespie# ex:ts=8 sw=4:
2*9cb26fd5Sespie# $OpenBSD: AddDelete.pm,v 1.100 2023/07/02 13:33:10 espie Exp $
3f76cebffSespie#
433efc49fSespie# Copyright (c) 2007-2010 Marc Espie <espie@openbsd.org>
533efc49fSespie#
633efc49fSespie# Permission to use, copy, modify, and distribute this software for any
733efc49fSespie# purpose with or without fee is hereby granted, provided that the above
833efc49fSespie# copyright notice and this permission notice appear in all copies.
933efc49fSespie#
1033efc49fSespie# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1133efc49fSespie# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1233efc49fSespie# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1333efc49fSespie# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1433efc49fSespie# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1533efc49fSespie# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1633efc49fSespie# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17f76cebffSespie#
18f76cebffSespie
19039cbdaaSespieuse v5.36;
20f76cebffSespie
213b55fdbbSespie# common behavior to pkg_add / pkg_delete
22f76cebffSespiepackage main;
23f76cebffSespieour $not;
24f76cebffSespie
2535135148Sespiepackage OpenBSD::PackingElement::FileObject;
26039cbdaaSespiesub retrieve_fullname($self, $state, $pkgname)
2735135148Sespie{
2835135148Sespie	return $state->{destdir}.$self->fullname;
2935135148Sespie}
3035135148Sespie
3135135148Sespiepackage OpenBSD::PackingElement::FileBase;
32039cbdaaSespiesub retrieve_size($self)
3335135148Sespie{
3435135148Sespie	return $self->{size};
3535135148Sespie}
3635135148Sespie
3735135148Sespiepackage OpenBSD::PackingElement::SpecialFile;
3835135148Sespieuse OpenBSD::PackageInfo;
39039cbdaaSespiesub retrieve_fullname($self, $state, $pkgname)
4035135148Sespie{
4135135148Sespie	return installed_info($pkgname).$self->name;
4235135148Sespie}
4335135148Sespie
4435135148Sespiepackage OpenBSD::PackingElement::FCONTENTS;
45039cbdaaSespiesub retrieve_size($self)
4635135148Sespie{
4735135148Sespie	my $size = 0;
4835135148Sespie	my $cname = $self->fullname;
4935135148Sespie	if (defined $cname) {
5035135148Sespie		$size = (stat $cname)[7];
5135135148Sespie	}
5235135148Sespie	return $size;
5335135148Sespie}
5435135148Sespie
5535135148Sespie
56f76cebffSespiepackage OpenBSD::AddDelete;
57f76cebffSespieuse OpenBSD::Error;
58f76cebffSespieuse OpenBSD::Paths;
59a409537dSespieuse OpenBSD::PackageInfo;
60a409537dSespieuse OpenBSD::AddCreateDelete;
615a69ed8cSespieour @ISA = qw(OpenBSD::AddCreateDelete);
62f76cebffSespie
63039cbdaaSespiesub do_the_main_work($self, $state)
64f76cebffSespie{
65a409537dSespie	if ($state->{bad}) {
66138429bfSespie		return;
67f76cebffSespie	}
68f76cebffSespie
6957ad4379Ssthen	umask 0022;
7057ad4379Ssthen
717e83eca3Sespie	my $handler = sub { $state->fatal("Caught SIG#1", shift); };
72f76cebffSespie	local $SIG{'INT'} = $handler;
73f76cebffSespie	local $SIG{'QUIT'} = $handler;
74f76cebffSespie	local $SIG{'HUP'} = $handler;
75f76cebffSespie	local $SIG{'KILL'} = $handler;
76f76cebffSespie	local $SIG{'TERM'} = $handler;
77f76cebffSespie
783c025a5eSespie	if ($state->defines('pkg-debug')) {
79a409537dSespie		$self->main($state);
80f76cebffSespie	} else {
81a409537dSespie		eval { $self->main($state); };
82f76cebffSespie	}
83f76cebffSespie	my $dielater = $@;
8430909ac4Sespie	return $dielater;
8530909ac4Sespie}
8630909ac4Sespie
87039cbdaaSespiesub handle_end_tags($self, $state)
88569cdac4Sespie{
89569cdac4Sespie	return if !defined $state->{tags}{atend};
90569cdac4Sespie	$state->progress->for_list("Running tags",
91569cdac4Sespie	    [keys %{$state->{tags}{atend}}],
92039cbdaaSespie	    sub($k) {
93569cdac4Sespie		return if $state->{tags}{deleted}{$k};
94569cdac4Sespie		return if $state->{tags}{superseded}{$k};
95569cdac4Sespie		$state->{tags}{atend}{$k}->run_tag($state);
96569cdac4Sespie	    });
97569cdac4Sespie}
98569cdac4Sespie
99039cbdaaSespiesub run_command($self, $state)
10030909ac4Sespie{
1018d5333baSespie	lock_db($state->{not}, $state) unless $state->defines('nolock');
10230909ac4Sespie	$state->check_root;
103a409537dSespie	$self->process_parameters($state);
104a409537dSespie	my $dielater = $self->do_the_main_work($state);
105f76cebffSespie	# cleanup various things
106569cdac4Sespie	$self->handle_end_tags($state);
1077255fd1aSespie	$state->{recorder}->cleanup($state);
108a6526ca6Sespie	$state->ldconfig->ensure;
109df8a9707Sespie	OpenBSD::PackingElement->finish($state);
110f76cebffSespie	$state->progress->clear;
111f76cebffSespie	$state->log->dump;
112a409537dSespie	$self->finish_display($state);
113a409537dSespie	if ($state->verbose >= 2 || $state->{size_only} ||
114a409537dSespie	    $state->defines('tally')) {
115e74b30b0Sespie		$state->vstat->tally;
116e74b30b0Sespie	}
11730909ac4Sespie	# show any error, and show why we died...
11830909ac4Sespie	rethrow $dielater;
11930909ac4Sespie}
12030909ac4Sespie
121039cbdaaSespiesub parse_and_run($self, $cmd)
122a409537dSespie{
1238a660df1Sespie	my $state = $self->new_state($cmd);
1248a660df1Sespie	$state->handle_options;
125790e15f9Sespie
12617323cb3Sespie	local $SIG{'INFO'} = sub { $state->status->print($state); };
12717323cb3Sespie
12817323cb3Sespie	my ($lflag, $termios);
12917323cb3Sespie	if ($self->silence_children($state)) {
130790e15f9Sespie		require POSIX;
131790e15f9Sespie
13217323cb3Sespie		$termios = POSIX::Termios->new;
133790e15f9Sespie
134790e15f9Sespie		if (defined $termios->getattr) {
135790e15f9Sespie			$lflag = $termios->getlflag;
136790e15f9Sespie		}
137790e15f9Sespie
138790e15f9Sespie		if (defined $lflag) {
139790e15f9Sespie			my $NOKERNINFO = 0x02000000; # not defined in POSIX
140790e15f9Sespie			$termios->setlflag($lflag | $NOKERNINFO);
141790e15f9Sespie			$termios->setattr;
142790e15f9Sespie		}
14317323cb3Sespie	}
144a409537dSespie
1455a69ed8cSespie	$self->try_and_run_command($state);
146790e15f9Sespie
147790e15f9Sespie	if (defined $lflag) {
148790e15f9Sespie		$termios->setlflag($lflag);
149790e15f9Sespie		$termios->setattr;
150790e15f9Sespie	}
15117323cb3Sespie
152*9cb26fd5Sespie	return $self->exit_code($state);
153*9cb26fd5Sespie}
154*9cb26fd5Sespie
155*9cb26fd5Sespiesub exit_code($self, $state)
156*9cb26fd5Sespie{
157138429bfSespie	return $state->{bad} != 0;
158a409537dSespie}
159f76cebffSespie
1603b55fdbbSespie# $self->silence_children($state)
161039cbdaaSespiesub silence_children($, $)
16217323cb3Sespie{
163*9cb26fd5Sespie	1;
16417323cb3Sespie}
16517323cb3Sespie
16646412527Sespie# nothing to do
167039cbdaaSespiesub tweak_list($, $)
16846412527Sespie{
16946412527Sespie}
17046412527Sespie
171039cbdaaSespiesub process_setlist($self, $state)
17246412527Sespie{
17346412527Sespie	$state->tracker->todo(@{$state->{setlist}});
17446412527Sespie	# this is the actual very small loop that processes all sets
17546412527Sespie	while (my $set = shift @{$state->{setlist}}) {
17646412527Sespie		$state->status->what->set($set);
17746412527Sespie		$set = $set->real_set;
17846412527Sespie		next if $set->{finished};
17946412527Sespie		$state->progress->set_header('Checking packages');
18046412527Sespie		unshift(@{$state->{setlist}}, $self->process_set($set, $state));
18146412527Sespie		$self->tweak_list($state);
18246412527Sespie	}
18346412527Sespie}
18446412527Sespie
185f76cebffSespiepackage OpenBSD::SharedItemsRecorder;
186039cbdaaSespiesub new($class)
187f76cebffSespie{
188f76cebffSespie	return bless {}, $class;
189f76cebffSespie}
190f76cebffSespie
191039cbdaaSespiesub is_empty($self)
192f76cebffSespie{
193f76cebffSespie	return !(defined $self->{dirs} or defined $self->{users} or
194f76cebffSespie	    defined $self->{groups});
195f76cebffSespie}
196f76cebffSespie
197039cbdaaSespiesub cleanup($self, $state)
198f76cebffSespie{
199f76cebffSespie	return if $self->is_empty or $state->{not};
200f76cebffSespie
201f76cebffSespie	require OpenBSD::SharedItems;
202f76cebffSespie	OpenBSD::SharedItems::cleanup($self, $state);
203f76cebffSespie}
204f76cebffSespie
205a409537dSespiepackage OpenBSD::AddDelete::State;
206ccf6490bSespieuse OpenBSD::Vstat;
2075f05097cSespieuse OpenBSD::Log;
208a409537dSespieour @ISA = qw(OpenBSD::AddCreateDelete::State);
209f76cebffSespie
210039cbdaaSespiesub handle_options($state, $opt_string, @usage)
21105e2d26cSespie{
2128af95b1cSespie	$state->{extra_stats} = 0;
213039cbdaaSespie	$state->{opt}{V} = sub() {
2148af95b1cSespie		$state->{extra_stats}++;
21505e2d26cSespie	};
2168a660df1Sespie	$state->{no_exports} = 1;
2173f0a1a28Sespie	$state->add_interactive_options;
2188af95b1cSespie	$state->SUPER::handle_options($opt_string.'aciInqsVB:', @usage);
21905e2d26cSespie
22005e2d26cSespie	if ($state->opt('s')) {
22105e2d26cSespie		$state->{not} = 1;
22205e2d26cSespie	}
22305e2d26cSespie	# XXX RequiredBy
22405e2d26cSespie	$main::not = $state->{not};
22505e2d26cSespie	$state->{localbase} = $state->opt('L') // OpenBSD::Paths->localbase;
2268cbfaa7dSespie	$ENV{PATH} = join(':',
2278cbfaa7dSespie	    '/bin',
2288cbfaa7dSespie	    '/sbin',
2298cbfaa7dSespie	    '/usr/bin',
2308cbfaa7dSespie	    '/usr/sbin',
2318cbfaa7dSespie	    '/usr/X11R6/bin',
2328cbfaa7dSespie	    "$state->{localbase}/bin",
2338cbfaa7dSespie	    "$state->{localbase}/sbin");
2348cbfaa7dSespie
23505e2d26cSespie	$state->{size_only} = $state->opt('s');
2366b6947a6Sespie	$state->{quick} = $state->opt('q');
23705e2d26cSespie	$state->{extra} = $state->opt('c');
23870363972Sespie	$state->{automatic} = $state->opt('a') // 0;
23905e2d26cSespie	$ENV{'PKG_DELETE_EXTRA'} = $state->{extra} ? "Yes" : "No";
24096acc640Sespie	if ($state->{not} || $state->defines('DONTLOG')) {
2419eb01df5Sespie		$state->{loglevel} = 0;
2429eb01df5Sespie	}
2436b6947a6Sespie	$state->{loglevel} //= 1;
2449eb01df5Sespie	if ($state->{loglevel}) {
2459eb01df5Sespie		require Sys::Syslog;
2469eb01df5Sespie		Sys::Syslog::openlog($state->{cmd}, "nofatal");
2479eb01df5Sespie	}
2486b6947a6Sespie	$state->{wantntogo} = $state->{extra_stats};
249c9685e2aSespie	if (defined $ENV{PKG_CHECKSUM}) {
250c9685e2aSespie		$state->{subst}->add('checksum', 1);
251c9685e2aSespie	}
252be5dca62Sespie	my $base = $state->opt('B') // '';
253be5dca62Sespie	if ($base ne '') {
254be5dca62Sespie		$base.='/' unless $base =~ m/\/$/o;
255be5dca62Sespie	}
256be5dca62Sespie	$state->{destdir} = $base;
25705e2d26cSespie}
25805e2d26cSespie
259039cbdaaSespiesub init($self, @p)
260f76cebffSespie{
2615f05097cSespie	$self->{l} = OpenBSD::Log->new($self);
262ccf6490bSespie	$self->{vstat} = OpenBSD::Vstat->new($self);
26364412b1bSespie	$self->{status} = OpenBSD::Status->new;
26464412b1bSespie	$self->{recorder} = OpenBSD::SharedItemsRecorder->new;
265e74b30b0Sespie	$self->{v} = 0;
266039cbdaaSespie	$self->SUPER::init(@p);
267a7d81fe1Sespie	$self->{export_level}++;
268f76cebffSespie}
269f76cebffSespie
270039cbdaaSespiesub syslog($self, @p)
271de512720Sespie{
272de512720Sespie	return unless $self->{loglevel};
273039cbdaaSespie	Sys::Syslog::syslog('info', $self->f(@p));
274de512720Sespie}
275de512720Sespie
276039cbdaaSespiesub ntodo($state, $offset)
277fa7e75beSespie{
278fa7e75beSespie	return $state->tracker->sets_todo($offset);
279fa7e75beSespie}
280fa7e75beSespie
281d2f781d7Sespie# one-level dependencies tree, for nicer printouts
282039cbdaaSespiesub build_deptree($state, $set, @deps)
283d2f781d7Sespie{
2843b55fdbbSespie	if (defined $state->{deptree}{$set}) {
2853b55fdbbSespie		$set = $state->{deptree}{$set};
286d2f781d7Sespie	}
287d2f781d7Sespie	for my $dep (@deps) {
288039cbdaaSespie		$state->{deptree}{$dep} = $set
289039cbdaaSespie		    unless defined $state->{deptree}{$dep};
290d2f781d7Sespie	}
291d2f781d7Sespie}
292d2f781d7Sespie
293039cbdaaSespiesub deptree_header($state, $pkg)
294d2f781d7Sespie{
295039cbdaaSespie	if (defined $state->{deptree}{$pkg}) {
296039cbdaaSespie		my $s = $state->{deptree}{$pkg}->real_set;
297d2f781d7Sespie		if ($s eq $pkg) {
298039cbdaaSespie			delete $state->{deptree}{$pkg};
299d2f781d7Sespie		} else {
300d2f781d7Sespie			return $s->short_print.':';
301d2f781d7Sespie		}
302d2f781d7Sespie	}
303d2f781d7Sespie	return '';
304d2f781d7Sespie}
305d2f781d7Sespie
306039cbdaaSespiesub vstat($self)
3074c82e4b5Sespie{
308a409537dSespie	return $self->{vstat};
3094c82e4b5Sespie}
3104c82e4b5Sespie
311039cbdaaSespiesub log($self, @p)
312f76cebffSespie{
313039cbdaaSespie	if (@p == 0) {
314f76cebffSespie		return $self->{l};
315f76cebffSespie	} else {
316039cbdaaSespie		$self->{l}->say(@p);
317f76cebffSespie	}
318f76cebffSespie}
319f76cebffSespie
320039cbdaaSespiesub run_quirks($state, $sub)
321875cde4bSespie{
322875cde4bSespie	if (!exists $state->{quirks}) {
323875cde4bSespie		eval {
324f001b114Sespie			use lib ('/usr/local/libdata/perl5/site_perl');
325875cde4bSespie			require OpenBSD::Quirks;
326875cde4bSespie			# interface version number.
327875cde4bSespie			$state->{quirks} = OpenBSD::Quirks->new(1);
328875cde4bSespie		};
3299c45d37dSespie		if ($@ && !$state->{not}) {
3306fe055f5Sespie			my $show = $state->verbose >= 2;
3316fe055f5Sespie			if (!$show) {
3326fe055f5Sespie				my $l = $state->repo->installed->match_locations(OpenBSD::Search::Stem->new('quirks'));
3336fe055f5Sespie				$show = @$l > 0;
3346fe055f5Sespie			}
3356fe055f5Sespie			$state->errsay("Can't load quirk: #1", $@) if $show;
33651ac1ebdSespie			# XXX cache that this didn't work
337875cde4bSespie			$state->{quirks} = undef;
338875cde4bSespie		}
339875cde4bSespie	}
340875cde4bSespie
341875cde4bSespie	if (defined $state->{quirks}) {
342875cde4bSespie		eval {
343875cde4bSespie			&$sub($state->{quirks});
344875cde4bSespie		};
345875cde4bSespie		if ($@) {
346875cde4bSespie			$state->errsay("Bad quirk: #1", $@);
347875cde4bSespie		}
348875cde4bSespie	}
349875cde4bSespie}
350875cde4bSespie
351039cbdaaSespiesub check_root($state)
352f76cebffSespie{
353a409537dSespie	if ($< && !$state->defines('nonroot')) {
354f76cebffSespie		if ($state->{not}) {
3557e83eca3Sespie			$state->errsay("#1 should be run as root",
3567e83eca3Sespie			    $state->{cmd}) if $state->verbose;
357f76cebffSespie		} else {
3587e83eca3Sespie			$state->fatal("#1 must be run as root", $state->{cmd});
359f76cebffSespie		}
360f76cebffSespie	}
361f76cebffSespie}
362f76cebffSespie
363039cbdaaSespiesub choose_location($state, $name, $list, $is_quirks = 0)
364f76cebffSespie{
365f76cebffSespie	if (@$list == 0) {
366c6ec65baSespie		if (!$is_quirks) {
367c6ec65baSespie			$state->errsay("Can't find #1", $name);
368875cde4bSespie			$state->run_quirks(
369039cbdaaSespie			    sub($quirks) {
370875cde4bSespie				$quirks->filter_obsolete([$name], $state);
371875cde4bSespie			    });
372c6ec65baSespie		}
373f76cebffSespie		return undef;
374f76cebffSespie	} elsif (@$list == 1) {
375f76cebffSespie		return $list->[0];
376f76cebffSespie	}
377f76cebffSespie
378f76cebffSespie	my %h = map {($_->name, $_)} @$list;
379eb8b7390Sespie	if ($state->is_interactive) {
380f76cebffSespie		$h{'<None>'} = undef;
381f76cebffSespie		$state->progress->clear;
382039cbdaaSespie		my $cmp = sub {		# XXX prototypable ?
383b48a274eSespie			return -1 if !defined $h{$a};
384b48a274eSespie			return 1 if !defined $h{$b};
385b48a274eSespie			my $r = $h{$a}->pkgname->to_pattern cmp
386b48a274eSespie				    $h{$b}->pkgname->to_pattern;
387b48a274eSespie			if ($r == 0) {
388b48a274eSespie				return $h{$a}->pkgname->{version}->
389b48a274eSespie				    compare($h{$b}->pkgname->{version});
390b48a274eSespie			} else {
391b48a274eSespie				return $r;
392b48a274eSespie			}
393b48a274eSespie		};
394b48a274eSespie		my $result = $state->ask_list("Ambiguous: choose package for $name", sort $cmp keys %h);
395f76cebffSespie		return $h{$result};
396f76cebffSespie	} else {
3977e83eca3Sespie		$state->errsay("Ambiguous: #1 could be #2",
3987e83eca3Sespie		    $name, join(' ', keys %h));
399f76cebffSespie		return undef;
400f76cebffSespie	}
401f76cebffSespie}
402f76cebffSespie
403039cbdaaSespiesub status($self)
40464412b1bSespie{
40564412b1bSespie	return $self->{status};
40664412b1bSespie}
40764412b1bSespie
408039cbdaaSespiesub replacing($self)
4098cbfaa7dSespie{
4108cbfaa7dSespie	return $self->{replacing};
4118cbfaa7dSespie}
4128cbfaa7dSespie
413a6526ca6SespieOpenBSD::Auto::cache(ldconfig,
414039cbdaaSespie    sub($self) {
415a6526ca6Sespie	return OpenBSD::LdConfig->new($self);
416a6526ca6Sespie    });
417a6526ca6Sespie
418ddd2e461Sespie# if we're not running as root, allow some stuff when not under /usr/local
419039cbdaaSespiesub allow_nonroot($state, $path)
420ddd2e461Sespie{
421ddd2e461Sespie	return $state->defines('nonroot') &&
422ddd2e461Sespie	    $path !~ m,^\Q$state->{localbase}/\E,;
423ddd2e461Sespie}
424ddd2e461Sespie
425039cbdaaSespiesub make_path($state, $path, $fullname)
426ddd2e461Sespie{
427ddd2e461Sespie	require File::Path;
428ddd2e461Sespie	if ($state->allow_nonroot($fullname)) {
429ddd2e461Sespie		eval {
430ddd2e461Sespie			File::Path::mkpath($path);
431ddd2e461Sespie		};
432ddd2e461Sespie	} else {
433ddd2e461Sespie		File::Path::mkpath($path);
434ddd2e461Sespie	}
435ddd2e461Sespie}
436ddd2e461Sespie
437a6526ca6Sespie# this is responsible for running ldconfig when needed
438a6526ca6Sespiepackage OpenBSD::LdConfig;
439a6526ca6Sespie
440039cbdaaSespiesub new($class, $state)
441a6526ca6Sespie{
442a6526ca6Sespie	bless { state => $state, todo => 0 }, $class;
443a6526ca6Sespie}
444a6526ca6Sespie
445a6526ca6Sespie# called once to figure out which directories are actually used
446039cbdaaSespiesub init($self)
447a6526ca6Sespie{
448a6526ca6Sespie	my $state = $self->{state};
449a6526ca6Sespie	my $destdir = $state->{destdir};
450a6526ca6Sespie
451a6526ca6Sespie	$self->{ldconfig} = [OpenBSD::Paths->ldconfig];
452a6526ca6Sespie
453a6526ca6Sespie	$self->{path} = {};
454a6526ca6Sespie	if ($destdir ne '') {
455a6526ca6Sespie		unshift @{$self->{ldconfig}}, OpenBSD::Paths->chroot, '--',
456a6526ca6Sespie		    $destdir;
457a6526ca6Sespie	}
458a6526ca6Sespie	open my $fh, "-|", @{$self->{ldconfig}}, "-r";
459a6526ca6Sespie	if (defined $fh) {
460a6526ca6Sespie		while (<$fh>) {
461a6526ca6Sespie			if (m/^\s*search directories:\s*(.*?)\s*$/o) {
462a6526ca6Sespie				for my $d (split(/\:/o, $1)) {
463a6526ca6Sespie					$self->{path}{$d} = 1;
464a6526ca6Sespie				}
465a6526ca6Sespie				last;
466a6526ca6Sespie			}
467a6526ca6Sespie		}
468a6526ca6Sespie		close($fh);
469a6526ca6Sespie	} else {
470a6526ca6Sespie		$state->errsay("Can't find ldconfig");
471a6526ca6Sespie	}
472a6526ca6Sespie}
473a6526ca6Sespie
474a6526ca6Sespie# called from libs to figure out whether ldconfig should be rerun
475039cbdaaSespiesub mark_directory($self, $name)
476a6526ca6Sespie{
477a6526ca6Sespie	if (!defined $self->{path}) {
478a6526ca6Sespie		$self->init;
479a6526ca6Sespie	}
480a6526ca6Sespie	require File::Basename;
481a6526ca6Sespie	my $d = File::Basename::dirname($name);
482a6526ca6Sespie	if ($self->{path}{$d}) {
483a6526ca6Sespie		$self->{todo} = 1;
484a6526ca6Sespie	}
485a6526ca6Sespie}
486a6526ca6Sespie
487a6526ca6Sespie# call before running any command (or at end) to run ldconfig just in time
488039cbdaaSespiesub ensure($self)
489a6526ca6Sespie{
490a6526ca6Sespie	if ($self->{todo}) {
491a6526ca6Sespie		my $state = $self->{state};
492a6526ca6Sespie		$state->vsystem(@{$self->{ldconfig}}, "-R")
493a6526ca6Sespie		    unless $state->{not};
494a6526ca6Sespie		$self->{todo} = 0;
495a6526ca6Sespie	}
496a6526ca6Sespie}
497a6526ca6Sespie
49864412b1bSespie# the object that gets displayed during status updates
49964412b1bSespiepackage OpenBSD::Status;
50064412b1bSespie
501039cbdaaSespiesub print($self, $state)
50264412b1bSespie{
50364412b1bSespie	my $what = $self->{what};
504039cbdaaSespie	$what //= 'Processing';
50564412b1bSespie	my $object;
50664412b1bSespie	if (defined $self->{object}) {
50764412b1bSespie		$object = $self->{object};
50864412b1bSespie	} elsif (defined $self->{set}) {
50964412b1bSespie		$object = $self->{set}->print;
51064412b1bSespie	} else {
51164412b1bSespie		$object = "Parameters";
51264412b1bSespie	}
51364412b1bSespie
5142d4feb81Sespie	$state->say($what." #1#2", $object, $state->ntogo_string);
515a409537dSespie	if ($state->defines('carp')) {
5166c02241bSespie		require Carp;
5176c02241bSespie		Carp::cluck("currently here");
5186c02241bSespie	}
51964412b1bSespie}
52064412b1bSespie
521039cbdaaSespiesub set($self, $set)
52264412b1bSespie{
52364412b1bSespie	delete $self->{object};
52464412b1bSespie	$self->{set} = $set;
52564412b1bSespie	return $self;
52664412b1bSespie}
52764412b1bSespie
528039cbdaaSespiesub object($self, $object)
52964412b1bSespie{
53064412b1bSespie	delete $self->{set};
53164412b1bSespie	$self->{object} = $object;
53264412b1bSespie	return $self;
53364412b1bSespie}
53464412b1bSespie
535039cbdaaSespiesub what($self, $what = undef)
53664412b1bSespie{
53764412b1bSespie	$self->{what} = $what;
53864412b1bSespie	return $self;
53964412b1bSespie}
54064412b1bSespie
541039cbdaaSespiesub new($class)
54264412b1bSespie{
54364412b1bSespie	bless {}, $class;
54464412b1bSespie}
54564412b1bSespie
546f76cebffSespie1;
547