Handle hostnames with upper-case letters
[webmin.git] / software / yum-lib.pl
1 # yum-lib.pl
2 # Functions for installing packages with yum
3
4 $yum_config = $config{'yum_config'} || "/etc/yum.conf";
5
6 sub list_update_system_commands
7 {
8 return ("yum");
9 }
10
11 # update_system_install([package], [&in])
12 # Install some package with yum
13 sub update_system_install
14 {
15 local $update = $_[0] || $in{'update'};
16 local $in = $_[1];
17 local $enable;
18 if ($in->{'enablerepo'}) {
19         $enable = "enablerepo=".quotemeta($in->{'enablerepo'});
20         }
21 local (@rv, @newpacks);
22 print "<b>",&text('yum_install', "<tt>yum $enable -y install $update</tt>"),"</b><p>\n";
23 print "<pre>";
24 &additional_log('exec', undef, "yum $enable -y install $update");
25 local $qm = join(" ", map { quotemeta($_) } split(/\s+/, $update));
26 &open_execute_command(CMD, "yum $enable -y install $qm </dev/null", 2);
27 while(<CMD>) {
28         s/\r|\n//g;
29         if (/^\[(update|install|deps):\s+(\S+)\s+/) {
30                 push(@rv, $2);
31                 }
32         elsif (/^(Installed|Dependency Installed|Updated|Dependency Updated):\s*(.*)/) {
33                 # Line like :
34                 # Updated:
35                 #   wbt-virtual-server-theme.x86
36                 local @pkgs = split(/\s+/, $2);
37                 if (!@pkgs) {
38                         # Wrapped to next line
39                         local $pkgs = <CMD>;
40                         $pkgs =~ s/^\s+//;
41                         $pkgs =~ s/\s+$//;
42                         @pkgs = split(/\s+/, $_);
43                         }
44                 foreach my $p (@pkgs) {
45                         if ($p !~ /:/ && $p =~ /^(\S+)\.(\S+)$/) {
46                                 my $pname = $1;
47                                 if ($p =~ /[^0-9\.\-\_i]/) {
48                                         push(@rv, $pname);
49                                         }
50                                 }
51                         }
52                 }
53         elsif (/^\s+Updating\s+:\s+(\S+)/) {
54                 # Line like :
55                 #   Updating       : wbt-virtual-server-theme       1/2 
56                 push(@rv, $1);
57                 }
58         if (!/ETA/ && !/\%\s+done\s+\d+\/\d+\s*$/) {
59                 print &html_escape($_."\n");
60                 }
61         }
62 close(CMD);
63 print "</pre>\n";
64 if ($?) {
65         print "<b>$text{'yum_failed'}</b><p>\n";
66         return ( );
67         }
68 else {
69         print "<b>$text{'yum_ok'}</b><p>\n";
70         return &unique(@rv);
71         }
72 }
73
74 # update_system_operations(packages)
75 # Given a list of packages, returns a list containing packages that will
76 # actually get installed, each of which is a hash ref with name and version.
77 sub update_system_operations
78 {
79 my ($packages) = @_;
80 my $temp = &transname();
81 &open_tempfile(SHELL, ">$temp", 0, 1);
82 &print_tempfile(SHELL, "install $packages\n");
83 &print_tempfile(SHELL, "transaction solve\n");
84 &close_tempfile(SHELL);
85 my @rv;
86 open(SHELL, "yum shell $temp |");
87 while(<SHELL>) {
88         if (/Package\s+(\S+)\s+(\S+)\s+set/i) {
89                 my $pkg = { 'name' => $1,
90                             'version' => $2 };
91                 if ($pkg->{'name'} =~ s/\.([^\.]+)$//) {
92                         $pkg->{'arch'} = $1;
93                         }
94                 if ($pkg->{'version'} =~ s/^(\S+)://) {
95                         $pkg->{'epoch'} = $1;
96                         }
97                 push(@rv, $pkg);
98                 }
99         }
100 close(SHELL);
101 &unlink_file($temp);
102 return @rv;
103 }
104
105 # show_update_system_opts()
106 # Returns HTML for enabling a repository, if any are disabled
107 sub show_update_system_opts
108 {
109 local @pinfo = &package_info("yum");
110 if (&compare_versions($pinfo[4], "2.1.10") > 0) {
111         local $conf = &get_yum_config();
112         local @ena;
113         foreach my $r (@$conf) {
114                 if ($r->{'values'}->{'enabled'} eq '0') {
115                         push(@ena, $r->{'name'});
116                         }
117                 }
118         if (@ena) {
119                 return $text{'yum_enable'}." ".
120                        &ui_select("enablerepo", "",
121                                   [ [ "", $text{'yum_none'} ],
122                                     map { [ $_ ] } @ena ]);
123                 }
124         }
125 return undef;
126 }
127
128 # update_system_form()
129 # Shows a form for updating all packages on the system
130 sub update_system_form
131 {
132 print &ui_subheading($text{'yum_form'});
133 print &ui_form_start("yum_upgrade.cgi");
134 print &ui_form_end([ [ undef, $text{'yum_apply'} ] ]);
135 }
136
137 # update_system_resolve(name)
138 # Converts a standard package name like apache, sendmail or squid into
139 # the name used by YUM.
140 sub update_system_resolve
141 {
142 local ($name) = @_;
143 return $name eq "apache" ? "httpd" :
144        $name eq "dhcpd" ? "dhcp" :
145        $name eq "mysql" ? "mysql mysql-server mysql-devel" :
146        $name eq "openssh" ? "openssh openssh-server" :
147        $name eq "postgresql" ? "postgresql postgresql-libs postgresql-server" :
148        $name eq "openldap" ? "openldap-servers openldap-clients" :
149                           $name;
150 }
151
152 # update_system_available()
153 # Returns a list of package names and versions that are available from YUM
154 sub update_system_available
155 {
156 local @rv;
157 local %done;
158 &open_execute_command(PKG, "yum info", 1, 1);
159 while(<PKG>) {
160         s/\r|\n//g;
161         if (/^Name\s*:\s*(\S+)/) {
162                 if ($done{$1}) {
163                         # Seen before .. update with newer info. This can happen
164                         # when YUM shows the installed version first.
165                         $pkg = $done{$1};
166                         delete($pkg->{'epoch'});
167                         delete($pkg->{'version'});
168                         }
169                 else {
170                         # Start of a new package
171                         $pkg = { 'name' => $1 };
172                         $done{$pkg->{'name'}} = $pkg;
173                         push(@rv, $pkg);
174                         }
175                 }
176         elsif (/^Arch\s*:\s*(\S+)/) {
177                 $pkg->{'arch'} = $1;
178                 }
179         elsif (/^Version\s*:\s*(\S+)/) {
180                 $pkg->{'version'} = $1;
181                 if ($pkg->{'version'} =~ s/^(\S+)://) {
182                         $pkg->{'epoch'} = $1;
183                         }
184                 }
185         elsif (/^Release\s*:\s*(\S+)/) {
186                 $pkg->{'version'} .= "-".$1;
187                 }
188         elsif (/^Repo\s*:\s*(\S+)/) {
189                 $pkg->{'source'} = $1;
190                 }
191         elsif (/^Summary\s*:\s*(\S.*)/) {
192                 $pkg->{'desc'} = $1;
193                 }
194         elsif (/^Epoch\s*:\s*(\S.*)/) {
195                 $pkg->{'epoch'} = $1;
196                 }
197         }
198 close(PKG);
199 &set_yum_security_field(\%done);
200 return @rv;
201 }
202
203 # set_yum_security_field(&package-hash)
204 # Set security field on packages which are security updates
205 sub set_yum_security_field
206 {
207 local ($done) = @_;
208 &open_execute_command(PKG, "yum list-sec 2>/dev/null", 1, 1);
209 while(<PKG>) {
210         s/\r|\n//g;
211         if (/^\S+\s+security\s+(\S+?)\-([0-9]\S+)\.([^\.]+)$/) {
212                 local ($name, $ver) = ($1, $2);
213                 if ($done->{$name}) {
214                         $done->{$name}->{'source'} = 'security';
215                         $done->{$name}->{'security'} = 1;
216                         }
217                 }
218         }
219 close(PKG);
220 }
221
222 # update_system_updates()
223 # Returns a list of package updates available from yum
224 sub update_system_updates
225 {
226 local @rv;
227 local %done;
228 &open_execute_command(PKG, "yum check-update 2>/dev/null", 1, 1);
229 while(<PKG>) {
230         s/\r|\n//g;
231         if (/^(\S+)\.([^\.]+)\s+(\S+)\s+(\S+)/) {
232                 local $pkg = { 'name' => $1,
233                                'arch' => $2,
234                                'version' => $3,
235                                'source' => $4 };
236                 if ($pkg->{'version'} =~ s/^(\S+)://) {
237                         $pkg->{'epoch'} = $1;
238                         }
239                 $done{$pkg->{'name'}} = $pkg;
240                 push(@rv, $pkg);
241                 }
242         }
243 close(PKG);
244 &set_yum_security_field(\%done);
245 return @rv;
246 }
247
248 # get_yum_config()
249 # Returns entries from the YUM config file, as a list of hash references
250 sub get_yum_config
251 {
252 local @rv;
253 local $sect;
254 open(CONF, $yum_config);
255 while(<CONF>) {
256         s/\r|\n//g;
257         s/^\s*#.*$//;
258         if (/^\s*\[(.*)\]/) {
259                 # Start of a section
260                 $sect = { 'name' => $1,
261                           'values' => { } };
262                 push(@rv, $sect);
263                 }
264         elsif (/^\s*(\S+)\s*=\s*(.*)/ && $sect) {
265                 # Value in a section
266                 $sect->{'values'}->{lc($1)} = $2;
267                 }
268         }
269 close(CONF);
270 return \@rv;
271 }
272
273 1;
274