1# ex:ts=8 sw=4: 2# $OpenBSD: AddCreateDelete.pm,v 1.57 2023/10/23 08:38:14 espie Exp $ 3# 4# Copyright (c) 2007-2014 Marc Espie <espie@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17# 18 19use v5.36; 20 21# common behavior to pkg_add, pkg_delete, pkg_create 22 23package OpenBSD::AddCreateDelete::State; 24our @ISA = qw(OpenBSD::State); 25 26use OpenBSD::State; 27use OpenBSD::ProgressMeter; 28 29sub init($self, @p) 30{ 31 $self->{progressmeter} = OpenBSD::ProgressMeter->new; 32 $self->{bad} = 0; 33 $self->SUPER::init(@p); 34 $self->{export_level}++; 35} 36 37sub progress($self) 38{ 39 return $self->{progressmeter}; 40} 41 42sub not($self) 43{ 44 return $self->{not}; 45} 46 47sub sync_display($self) 48{ 49 $self->progress->clear; 50} 51 52sub add_interactive_options($self) 53{ 54 $self->{has_interactive_options} = 1; 55 return $self; 56} 57 58my $setup = { 59 nowantlib => q' 60 use OpenBSD::Dependencies::SolverBase; 61 no warnings qw(redefine); 62 package OpenBSD::Dependencies::SolverBase; 63 sub solve_wantlibs($, $) { 1 } 64 ', 65 nosystemwantlib => q' 66 use OpenBSD::LibSpec; 67 package OpenBSD::Library::System; 68 sub no_match_dispatch($library, $spec, $base) 69 { 70 return $spec->no_match_name($library, $base); 71 } 72 ', 73 norun => q' 74 package OpenBSD::State; 75 sub _system(@) { 0 } 76 ', 77}; 78 79 80sub handle_options($state, $opt_string, @usage) 81{ 82 my $i; 83 84 if ($state->{has_interactive_options}) { 85 $opt_string .= 'iI'; 86 $state->{opt}{i} = sub() { 87 $i++; 88 }; 89 }; 90 91 $state->SUPER::handle_options($opt_string.'L:mnx', @usage); 92 93 $state->progress->setup($state->opt('x'), $state->opt('m'), $state); 94 $state->{not} = $state->opt('n'); 95 if ($state->{has_interactive_options}) { 96 if ($state->opt('I')) { 97 $i = 0; 98 } elsif (!defined $i) { 99 $i = -t STDIN; 100 } 101 } 102 $state->{interactive} = $state->interactive_class($i)->new($state, $i); 103 if ($state->defines('REGRESSION_TESTING')) { 104 for my $i (split(/[,\s]/, 105 $state->defines('REGRESSION_TESTING'))) { 106 $state->{regression}{$i} = 1; 107 if (defined $setup->{$i}) { 108 eval "$setup->{$i}"; 109 if ($@) { 110 $state->fatal( 111 "Regression testing #1: #2", 112 $i, $@); 113 } 114 } 115 } 116 } 117} 118 119sub interactive_class($, $i) 120{ 121 if ($i) { 122 require OpenBSD::Interactive; 123 return 'OpenBSD::Interactive'; 124 } else { 125 return 'OpenBSD::InteractiveStub'; 126 } 127} 128 129sub is_interactive($self) 130{ 131 return $self->{interactive}->is_interactive; 132} 133 134sub find_window_size($state) 135{ 136 $state->SUPER::find_window_size; 137 $state->{progressmeter}->compute_playfield; 138} 139 140sub handle_continue($state) 141{ 142 $state->SUPER::handle_continue; 143 $state->{progressmeter}->handle_continue; 144} 145 146sub confirm_defaults_to_no($self, @p) 147{ 148 return $self->{interactive}->confirm($self->f(@p), 0); 149} 150 151sub confirm_defaults_to_yes($self, @p) 152{ 153 return $self->{interactive}->confirm($self->f(@p), 1); 154} 155 156sub ask_list($self, @p) 157{ 158 return $self->{interactive}->ask_list(@p); 159} 160 161sub vsystem($self, @p) 162{ 163 if ($self->verbose < 2) { 164 $self->system(@p); 165 } else { 166 $self->verbose_system(@p); 167 } 168} 169 170sub system($self, @p) 171{ 172 $self->SUPER::system(@p); 173} 174 175sub run_makewhatis($state, $opts, $l) 176{ 177 my $braindead = sub() { chdir('/'); }; 178 while (@$l > 1000) { 179 my @b = splice(@$l, 0, 1000); 180 $state->vsystem($braindead, 181 OpenBSD::Paths->makewhatis, @$opts, '--', @b); 182 } 183 $state->vsystem($braindead, 184 OpenBSD::Paths->makewhatis, @$opts, '--', @$l); 185} 186 187# TODO this stuff is definitely not as clear as it could be 188sub ntogo($self, $offset = 0) 189{ 190 return $self->{wantntogo} ? 191 $self->progress->ntogo($self, $offset) : 192 $self->f("ok"); 193} 194 195sub ntogo_string($self, $offset = 0) 196{ 197 return $self->{wantntogo} ? 198 $self->f(" (#1)", $self->ntodo($offset)) : 199 $self->f(""); 200} 201 202sub solve_dependency($self, $solver, $dep, $package) 203{ 204 return $solver->really_solve_dependency($self, $dep, $package); 205} 206 207package OpenBSD::AddCreateDelete; 208use OpenBSD::Error; 209 210sub handle_options($self, $opt_string, $state, @usage) 211{ 212 $state->handle_options($opt_string, $self, @usage); 213} 214 215sub try_and_run_command($self, $state) 216{ 217 if ($state->defines('pkg-debug')) { 218 $self->run_command($state); 219 } else { 220 try { 221 $self->run_command($state); 222 } catch { 223 $state->errsay("#1: #2", $state->{cmd}, $_); 224 OpenBSD::Handler->reset; 225 if ($_ =~ m/^Caught SIG(\w+)/o) { 226 kill $1, $$; 227 } 228 $state->{bad}++; 229 }; 230 } 231} 232 233package OpenBSD::InteractiveStub; 234sub new($class, $, $) 235{ 236 bless {}, $class; 237} 238 239sub ask_list($, $, @values) 240{ 241 return $values[0]; 242} 243 244sub confirm($, $, $yesno) 245{ 246 return $yesno; 247} 248 249sub is_interactive($) 250{ 251 return 0; 252} 2531; 254