1 #!/usr/bin/env perl
2 #
3 # pkg-get - A binary package management utility for CRUX Linux
4 # Copyright (C) 2004-2006 Simone Rota <sip@varlock.com>
5 # Copyright (c) 2006-2013 by CRUX team (http://crux.nu)
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11
12 use warnings;
13 use strict;
14 use Getopt::Long;
15
16 my $VERSION = "0.4.6";
17 my $CFGFILE = "/etc/pkg-get.conf";
18 my $LOCKFILE = "/var/lib/pkg/pkg-get.locker";
19 my $PKGDB = "/var/lib/pkg/db" ;
20
21 $SIG{HUP} = \&trap; $SIG{INT} = \&trap; $SIG{QUIT} = \&trap; $SIG{TERM} = \&trap;
22
23 # Global vars
24 my @repos = (); # package repositories
25 my @donetasks; my @failtasks; my @prevtasks; my %pptasks; my %readmetasks;
26 my $curraction = ""; my %installed; my %deps; my @dependencies; my %missingdeps;
27
28 # CL Options
29 my $download_only; my $pre_install; my $post_install;
30 my $install_scripts; my $filter = ""; my $all; my $unused;
31 my $aargs=""; my $ignore_md5sum; my $force; my $root;
32 GetOptions("do"=>\$download_only,
33 "pre-install"=>\$pre_install, "post-install"=>\$post_install,
34 "install-scripts"=>\$install_scripts, "all"=>\$all,
35 "filter=s"=>\$filter, "config=s"=>\$CFGFILE, "aargs=s"=>\$aargs,
36 "f"=>\$force, "im"=>\$ignore_md5sum, "margs=s"=>\$unused,
37 "rargs=s"=>\$unused, "r=s"=>\$root);
38
39 # use compression-mode defined in pkgmk.conf
40 our $compress = "gz";
41 open CONFIG, "/etc/pkgmk.conf" or die "Could not open /etc/pkgmk.conf";
42 while (<CONFIG>) {
43 $compress = $1 if m/^PKGMK_COMPRESSION_MODE="(.*)"\n/;
44 }
45 close CONFIG;
46
47 if ($root) {
48 $LOCKFILE = $root.$LOCKFILE ;
49 $PKGDB = $root.$PKGDB;
50 }
51
52 # Get command, verify it's valid
53 my $command = getcommand(@ARGV);
54 if (index($command,"Error: ") eq 0 ) {
55 $command =~ s/Error\: //;
56 exiterr($command);
57 }
58 readconfig();
59
60 SWITCH: {
61 if ($command eq "version") { version(); last SWITCH; }
62 if ($command eq "sync") { sync(); last SWITCH; }
63 if ($command eq "info") { info(); last SWITCH; }
64 if ($command eq "help") { help(); last SWITCH; }
65 if ($command eq "readme") { readme(); last SWITCH; }
66 if ($command eq "search") { search(); last SWITCH; }
67 if ($command eq "dsearch") { dsearch(); last SWITCH; }
68 if ($command eq "list") { list(); last SWITCH; }
69 if ($command eq "path") { path(); last SWITCH; }
70 if ($command eq "remove") { remove(); last SWITCH; }
71 if ($command eq "listinst") { listinst(); last SWITCH; }
72 if ($command eq "lock") { dolock(); last SWITCH; }
73 if ($command eq "unlock") { unlock(); last SWITCH; }
74 if ($command eq "listlocked") { listlocked(); last SWITCH; }
75 if ($command eq "printf") { doprintf(); last SWITCH; }
76 if ($command eq "isinst") { isinst(); last SWITCH; }
77 if ($command eq "diff") { diff(); last SWITCH; }
78 if ($command eq "quickdiff") { quickdiff(); last SWITCH; }
79 if ($command eq "dup") { dup(); last SWITCH; }
80 if ($command eq "depends") { depends(); last SWITCH; }
81 if ($command eq "quickdep") { quickdep(); last SWITCH; }
82 if ($command eq "install") { install(@ARGV); last SWITCH; }
83 if ($command eq "update") { update(@ARGV); last SWITCH; }
84 if ($command eq "sysup") { sysup(); last SWITCH; }
85 if ($command eq "dependent") { dependent(); last SWITCH; }
86 if ($command eq "depinst") { depinst(); last SWITCH; }
87 if ($command eq "current") { current(); last SWITCH; }
88 }
89
90
91 ############################################################################
92 # Support functions
93 ############################################################################
94
95 # Exit with error
96 sub exiterr {
97 my ($msg) = @_;
98 print "pkg-get: $msg\n";
99 exit 1;
100 }
101
102 sub trap {
103 printresults(1);
104 die("\npkg-get: interrupted\n");
105 }
106
107 # Get command, return an error if not in the list of allowed commands
108 sub getcommand {
109 my @args = @_;
110 my $givencmd = $args[0];
111 my $givenarg = $args[1];
112 if (not $givenarg){$givenarg = ""};
113 if (not $givencmd){$givencmd = ""};
114 my @allowed = ("depinst:", "install:", "sysup", "diff", "update:", "depends:", "info:", "sync",
115 "version", "help", "quickdep:", "dependent:", "list", "listinst", "isinst:",
116 "search:", "dsearch:", "lock:", "unlock:", "listlocked", "quickdiff", "printf:",
117 "remove:", "readme:", "dup", "path:", "current:");
118
119 foreach my $valid(@allowed) {
120 if ($givencmd eq ""){
121 return "Error: no command given. try pkg-get help for more information";
122 }
123 if ($givencmd eq $valid) {
124 return $givencmd;
125 } elsif ($givencmd.":" eq $valid) {
126 if ($givenarg ne "") {
127 return $givencmd;
128 } else {
129 return "Error: '$givencmd' requires an argument";
130 }
131 }
132 }
133 return "Error: unknown command '$givencmd'. try pkg-get help for more information";
134 }
135
136 # Parses the configuration file
137 sub readconfig {
138 open(CFG, $CFGFILE)
139 or exiterr("could not open $CFGFILE");
140 while (<CFG>) {
141 chomp;
142 if ( /^pkgdir\s+/ ) {
143 my $repo = $_;
144 $repo =~ s/^pkgdir\s+//;
145 $repo =~ s/#(.*)$//;
146 $repo =~ s/\s+$//;
147 push @repos, $repo;
148 } elsif (/^runscripts\s+/) {
149 my $rs = $_;
150 $rs =~ s/^runscripts\s+//;
151 $rs =~ s/#(.*)$//;
152 $rs =~ s/\s+$//;
153 if ($rs eq "yes") {$install_scripts = 1};
154 }
155 }
156 close(CFG);
157 }
158
159 # Parse a line describing a package
160 sub parsepackage {
161 my @p = split(/\:/, $_[0]);
162 if ($#p != 6) {exiterr("$_[1]/PKGREPO appears to be in wrong format!\nAborting.")};
163 my %pkg;
164 my $name = $p[0];
165 $name =~ s/\#.*$//;
166 my $version = $p[0];
167 $version =~ s/^.*\#//;
168 $version =~ s/-\w*\.pkg\.tar\.[gbx]z*//;
169 my $release = $p[0];
170 $release =~ s/^.*-//;
171 $release =~ s/\.pkg\.tar\.[gbx]z*//;
172 if (not $_[2]) {$_[2] = $_[1]};
173 $pkg{'name'} = $name;
174 $pkg{'version'} = $version;
175 $pkg{'release'} = $release;
176 $pkg{'path'} = $_[1];
177 $pkg{'url'} = $_[2] . "/$p[0]";
178 $pkg{'size'} = $p[1];
179 $pkg{'md5sum'} = $p[2];
180 $pkg{'description'} = $p[3];
181 $pkg{'pre_install'} = $p[4];
182 $pkg{'post_install'} = $p[5];
183 $pkg{'readme'} = $p[6];
184 if ($_[3] == 1) {
185 getinstalled();
186 $pkg{'instversion'} = $installed{$name};
187 }
188 return %pkg;
189 }
190
191 # Parse a line describing a package (just the name)
192 sub parsepackagelight {
193 my @p = split(/\:/, $_[0]);
194 if ($#p != 6) {exiterr("$_[1]/PKGREPO appears to be in wrong format!\nAborting.")};
195 my %pkg;
196 my $name = $p[0];
197 $name =~ s/\#.*$//;
198 $pkg{'name'} = $name;
199 return %pkg;
200 }
201
202 # Print info about the given package
203 sub printinfo {
204 my %pkg = @_;
205 print "Name : " . $pkg{'name'} . "\n";
206 print "Version : " . $pkg{'version'} . "\n";
207 print "Release : " . $pkg{'release'} . "\n";
208 print "Description : " . $pkg{'description'} . "\n";
209 print "URL : " . $pkg{'url'} . "\n";
210 print "Md5sum : " . $pkg{'md5sum'} . "\n";
211 print "Size : " . $pkg{'size'} . "\n";
212 my $deps = getdirectdeps($pkg{'name'}, $pkg{'path'});
213 if ($deps ne "") { print "Depends on : $deps\n";};
214 my $files = "";
215 if ($pkg{'readme'} eq "yes") {$files .= "README,"};
216 if ($pkg{'pre_install'} eq "yes") {$files .= "pre-install,"};
217 if ($pkg{'post_install'} eq "yes") {$files .= "post-install,"};
218 $files =~ s/\,$//;
219 if ($files ne "") { print "Files : $files\n";};
220 }
221
222 # Get direct dependencies for package
223 sub getdirectdeps {
224 my $pkgname = $_[0];
225 my $dir = $_[1];
226 open(DEPS, "$dir/PKGDEPS")
227 or exiterr("could not open $dir/PKGDEPS");
228 while (<DEPS>) {
229 chomp;
230 if ( /^\Q$pkgname\E\s+/ ) {
231 my $dep = $_;
232 $dep =~ s/^.*\: //;
233 close(DEPS);
234 return $dep;
235 }
236 }
237 close(DEPS);
238 return "";
239 }
240
241 # Prints the README file to stdout
242 sub printreadme {
243 my %pkg = @_;
244 my $dir = $pkg{'path'};
245 my $pkgname = $pkg{'name'};
246 my $found = 0;
247 my $finished = 0;
248 open(READ, "$dir/PKGREAD")
249 or exiterr("could not open $dir/PKGREAD");
250 while (<READ>) {
251 if ($finished eq 1) {return;};
252 chomp;
253 if ($found eq 1) {
254 if ( /PKGREADME\:/ ) {
255 $finished = 1;
256 close(READ);
257 return;
258 } else {
259 print "$_\n";
260 }
261 }
262 if ($finished eq 0) {
263 if ( /PKGREADME: $pkgname$/ ) {
264 $found = 1;
265 }
266 }
267 }
268 close(READ);
269 }
270
271 # Print results for multiple package operations
272 sub printresults {
273 my $okaction = $curraction;
274 my $curr = "";
275 my $action;
276 my $pkg;
277 my @t;
278 my @readme;
279 my $goterror = 0;
280 if (@donetasks) {
281 print "\n-- Packages $okaction\n";
282 foreach my $task(@donetasks) {
283 if ($readmetasks{$task}) {push(@readme, $task)}
284 print "$task" . $pptasks{$task}."\n";
285 }
286 }
287 if (@prevtasks) {
288 if ($okaction eq "installed") {
289 print "\n-- Packages installed before this run (ignored)\n";
290 } else {
291 print "\n-- Packages not previously installed (ignored)\n";
292 }
293 foreach my $task(@prevtasks) {
294 print "$task\n";
295 }
296 }
297 if (@failtasks) {
298 @failtasks = sort(@failtasks);
299 foreach my $task(@failtasks) {
300 @t = split(/,/,$task);
301 $action = $t[0];
302 $pkg = $t[1];
303 if ($curr ne $action) {
304 print "\n-- Packages $action\n";
305 $curr = $action;
306 }
307 print "$pkg\n";
308 }
309 }
310 if (@readme) {
311 print "\n-- $okaction packgages with README file\n";
312 foreach my $task(@readme) {
313 print "$task" . $pptasks{$task}."\n";
314 }
315 }
316 if(@donetasks and not @failtasks and not $_[0]) {
317 print "\npkg-get: $okaction successfully\n"
318 }
319 }
320
321 # Get the list of installed packages
322 sub getinstalled {
323 if (%installed) {
324 return;
325 }
326 my $name;
327 my $version;
328 my $sec = 0;
329 open(DB, $PKGDB)
330 or exiterr("could not open ".$PKGDB);
331 while (<DB>) {
332 chomp;
333 if ($_ ne "") {
334 if ($sec == 0) {
335 $name = $_;
336 $sec = 1;
337 } elsif ($sec == 1) {
338 $version = $_;
339 $sec = 3;
340 }
341 }
342 if ($sec == 3) {
343 if ($_ eq "") {
344 $sec = 0;
345 $installed{$name} = $version;
346 }
347 }
348 }
349 close(DB);
350 }
351
352 # Lock the given pkgname
353 sub lockadd {
354 my $pkg = $_[0];
355 my @locked = ();
356 if (not -e $LOCKFILE) {
357 open(LCK, "+>> $LOCKFILE") or exiterr("could not write to lock file");
358 close(LCK);
359 }
360 open(LCK, $LOCKFILE);
361 while (<LCK>) {
362 chomp;
363 if ($_ eq $pkg) {
364 print "Already locked: $pkg\n";
365 close(LCK);
366 return;
367 } else {
368 push (@locked, $_);
369 }
370 }
371 close(LCK);
372 push(@locked, $pkg);
373 @locked = sort(@locked);
374 open(LCK, "> $LOCKFILE") or exiterr("could not write to lock file");
375 foreach my $lock(@locked) {
376 print LCK "$lock\n";
377 }
378 close(LCK);
379 }
380
381 # Rrint formatted info for given package
382 sub formattedprint {
383 my %pkg = @_;
384 my $fmt = $ARGV[1];
385 $fmt =~ s|%n|$pkg{'name'}|;
386 $fmt =~ s|%p|$pkg{'path'}|;
387 $fmt =~ s|%v|$pkg{'version'}|;
388 $fmt =~ s|%r|$pkg{'release'}|;
389 $fmt =~ s|%d|$pkg{'description'}|;
390 $fmt =~ s|%u|$pkg{'url'}|;
391 $fmt =~ s|%R|$pkg{'readme'}|;
392 $fmt =~ s|%E|$pkg{'pre_install'}|;
393 $fmt =~ s|%O|$pkg{'post_install'}|;
394 $fmt =~ s|%M|Nobody|; # for prt-get compatibility
395 $fmt =~ s|%P|Nobody|; # for prt-get compatibility
396 $fmt =~ s|\\n|\n|;
397 $fmt =~ s|\\t|\t|;
398 if (index($fmt,"%e") >=0) {
399 my $deps = getdirectdeps($pkg{'name'}, $pkg{'path'});
400 $fmt =~ s|%e|$deps|;
401 }
402 if (index($fmt,"%l") >=0) {
403 my $locked = islocked($pkg{'name'});
404 $fmt =~ s|%l|$locked|;
405 }
406 if (index($fmt,"%i") >=0) {
407 my $inst = "no";
408 if ($pkg{'instversion'}) {
409 if ($pkg{'instversion'} eq $pkg{'version'}."-".$pkg{'release'}) {
410 $inst = "yes";
411 } else {
412 $inst = "diff";
413 }
414 }
415 $fmt =~ s|%i|$inst|;
416 }
417 print "$fmt";
418 }
419
420 # See if package is currently locked
421 sub islocked {
422 my $pkg = $_[0];
423 open(LCK, $LOCKFILE) or return "no";
424 while (<LCK>) {
425 chomp;
426 if ($_ eq $pkg) {
427 close(LCK);
428 return "yes";
429 }
430 }
431 close(LCK);
432 return "no";
433 }
434
435 # Get package from the repo(s)
436 sub getpackage {
437 my $pkgname = $_[0];
438 my $checkver = $_[1];
439 my %found;
440 my %res;
441 foreach my $repo(@repos) {
442 my @r = split(/\|/, $repo);
443 my $dir = $r[0];
444 my $url = $r[1];
445 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
446 while (<REPO>) {
447 chomp;
448 my %pkg = parsepackage($_, $dir, $url, $checkver);
449 if ($pkg{'name'} eq $pkgname) {
450 close (REPO);
451 return %pkg;
452 }
453 }
454 close (REPO);
455 }
456 return %res;
457 }
458
459 # Get short status for package, ie [i]
460 sub getshortstatus {
461 my %pkg = @_;
462 if ($pkg{'instversion'}) {
463 if ($pkg{'instversion'} eq $pkg{'version'}."-".$pkg{'release'}) {
464 return "[i]";
465 } else {
466 return "[u]";
467 }
468 }
469 return "[ ]";
470 }
471
472 # Get (recursive) dependencies for pkgname
473 sub getdependencies {
474 my $pkgname = $_[0];
475 my $checkver = $_[1];
476 my $pkgparent = $_[2];
477 my $depstring = "";
478 if ($pkgparent eq "") {
479 #%deps = ();
480 };
481 if (not $deps{$pkgname}) {
482 my %pkg = getpackage($pkgname, 1);
483 if (%pkg) {
484 my $ddeps = getdirectdeps($pkg{'name'}, $pkg{'path'});
485 my @d = split(/,/, $ddeps);
486 foreach my $dep(@d) {
487 getdependencies($dep, $checkver, $pkgname);
488 }
489 if ($checkver) {
490 $depstring = getshortstatus(%pkg) . " $pkgname";
491 } else {
492 $depstring = $pkgname;
493 }
494 $deps{$pkgname} = $depstring;
495 push(@dependencies, $depstring);
496 } else {
497 if ($pkgparent eq "") {
498 return 0;
499 } else {
500 $missingdeps{$pkgname} = $pkgparent;
501 }
502 }
503 }
504 }
505
506 # Download given package (if needed), check md5sum
507 sub downloadpkg {
508 my %pkg = @_;
509 my $fullpath = $pkg{'path'}."/".$pkg{'name'}."#".$pkg{'version'}."-".$pkg{'release'}.".pkg.tar.$compress";
510 if (-f $fullpath) {
511 my $md5 = `md5sum $fullpath`; chomp;
512 $md5 =~ s/\s+.*$//;
513 $md5 =~ chop($md5);
514 if ($md5 ne $pkg{'md5sum'} and not $ignore_md5sum) {
515 print STDERR "=======> ERROR: md5sum mismatch for $pkg{'name'}:\n";
516 print STDERR "required : $pkg{'md5sum'}\n";
517 print STDERR "found : $md5\n";
518 return 0;
519 }
520 return 1;
521 } else {
522 if ($pkg{'url'} eq "") {return 1}; # repo is local and pkg does not exist.
523 my $url = $pkg{'url'};
524 $url =~ s/\#/\%23/;
525 system ("wget --no-directories --tries=3 --waitretry=3 --directory-prefix=$pkg{'path'} $url") == 0 or return 0;
526 my $md5 = `md5sum $fullpath`; chomp;
527 $md5 =~ s/\s+.*$//;
528 $md5 =~ chop($md5);
529 if ($md5 ne $pkg{'md5sum'} and not $ignore_md5sum) {
530 print STDERR "=======> ERROR: md5sum mismatch for $pkg{'name'}:\n";
531 print STDERR "required : $pkg{'md5sum'}\n";
532 print STDERR "found : $md5\n";
533 return 0;
534 }
535 }
536 return 1;
537 }
538
539 # Install given package
540 sub installpkg {
541 my $upgrade = shift(@_);
542 my %pkg = @_;
543 my $aa = $aargs." ";
544 if ($pkg{'readme'} eq "yes") {$readmetasks{$pkg{'name'}} = 1};
545 $pptasks{$pkg{'name'}} = "";
546 if ($download_only) {return 1};
547 if ($force){$aa = $aa."-f "};
548 if ($root) {$aa = $aa."-r ".$root." "};
549 if ($pkg{'pre_install'} eq "yes" and ($install_scripts or $pre_install)) {dopre(%pkg)};
550 my $fullpath = $pkg{'path'}."/".$pkg{'name'}."#".$pkg{'version'}."-".$pkg{'release'}.".pkg.tar.$compress";
551 print "pkg-get: /usr/bin/pkgadd $upgrade$aa$fullpath\n";
552 system ("/usr/bin/pkgadd $upgrade$aa$fullpath") == 0 or return 0;
553 if ($pkg{'post_install'} eq "yes" and ($install_scripts or $post_install)) {dopost(%pkg)};
554 return 1;
555 }
556
557 # Execute pre-install script
558 sub dopre {
559 my %pkg = @_;
560 my $cmd = "/bin/bash $pkg{'path'}/PKGINST $pkg{name}_pre_install";
561 if (system($cmd) == 0){
562 $pptasks{$pkg{'name'}} .= " [pre: ok]";
563 } else {
564 $pptasks{$pkg{'name'}} .= " [pre: failed]";
565 }
566 }
567
568 # Execute post-install script
569 sub dopost {
570 my %pkg = @_;
571 my $cmd = "/bin/bash $pkg{'path'}/PKGINST $pkg{name}_post_install";
572 if (system($cmd) == 0){
573 $pptasks{$pkg{'name'}} .= " [post: ok]";
574 } else {
575 $pptasks{$pkg{'name'}} .= " [post: failed]";
576 }
577 }
578
579 ############################################################################
580 # Main functions (commands)
581 ############################################################################
582
583 # No pun intended ##########################################################
584 sub version {
585 print "pkg-get $VERSION ";
586 print "by Simone Rota <sip\@varlock.com>\n";
587 }
588
589 # Show brief help ##########################################################
590 sub help {
591 print "Usage: pkg-get command <package1> [package2 ... packageN] [options]
592
593 Some command:
594 sync synchronize with the repository
595 depinst install package and its dependencies;
596 info info about package
597 sysup updates all outdated packages
598 diff list all outdated packages
599
600 Some option:
601 -do download only
602 --install-scripts use install scripts
603 -r <root> use <root> for pkgadd
604
605 Example:
606 pkg-get install sqlite pysqlite
607
608 For other commands and samples, see the pkg-get(8) man page\n";
609 }
610
611 # Sync with the remote server(s) ###########################################
612 sub sync {
613 my @r;
614 my $dir;
615 my $url;
616 my $dlerror = 0;
617 foreach my $repo(@repos) {
618 @r = split(/\|/, $repo);
619 $dir = $r[0];
620 $url = $r[1];
621 if (not $url){$url = ""};
622 print "Updating collection $dir\n";
623 if (not -d $dir) {
624 mkdir($dir) or exiterr("cannot create $dir");
625 }
626 if ($url ne "") {
627 for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") {
628 if (-f "$dir/$f") {rename("$dir/$f", "$dir/$f.old") or exiterr("cannot write to $dir")};
629 if (system("wget -q -P $dir $url/$f") != 0) {
630 print " cannot retrieve $f\n";
631 $dlerror=1;
632 }
633 }
634 if ($dlerror) { # restore backup repo
635 for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") {
636 if (-f "$dir/$f.old") {rename("$dir/$f.old", "$dir/$f") or exiterr("cannot write to $dir")};};
637 } else { # remove backup repo
638 for my $f ("PKGREPO", "PKGDEPS", "PKGREAD", "PKGINST") {
639 if (-f "$dir/$f.old") {unlink("$dir/$f.old") or exiterr("cannot write to $dir")};};
640 }
641 }
642 }
643 }
644
645 # Show info about the package ##############################################
646 sub info {
647 my $arg = $ARGV[1];
648 foreach my $repo(@repos) {
649 my @r = split(/\|/, $repo);
650 my $dir = $r[0];
651 my $url = $r[1];
652 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
653 while (<REPO>) {
654 chomp;
655 my %pkg = parsepackage($_, $dir, $url, 0);
656 if ($pkg{'name'} eq $arg) {
657 printinfo(%pkg);
658 close(REPO);
659 return;
660 }
661 }
662 close(REPO);
663 }
664 print "Package '$arg' not found\n";
665 }
666
667 # List packages containing given string in their name ######################
668 sub search {
669 my $arg = $ARGV[1];
670 my %found;
671 foreach my $repo(@repos) {
672 my @r = split(/\|/, $repo);
673 my $dir = $r[0];
674 my $url = $r[1];
675 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
676 while (<REPO>) {
677 chomp;
678 my %pkg = parsepackage($_, $dir, $url, 0);
679 if (index($pkg{'name'}, $arg) > -1 and not $found{$pkg{'name'}}) {
680 $found{$pkg{'name'}} = 1;
681 }
682 }
683 close(REPO);
684 }
685 foreach my $key (sort keys %found) {
686 print "$key\n";
687 }
688 if (not %found) {print "No matching packages found\n"};
689 }
690
691 # List packages containing given string (name / description) ###############
692 sub dsearch {
693 my $arg = $ARGV[1];
694 my %found;
695 foreach my $repo(@repos) {
696 my @r = split(/\|/, $repo);
697 my $dir = $r[0];
698 my $url = $r[1];
699 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
700 while (<REPO>) {
701 chomp;
702 my %pkg = parsepackage($_, $dir, $url, 0);
703 if ((index($pkg{'name'}, $arg) > -1 or index($pkg{'description'}, $arg) > -1)
704 and not $found{$pkg{'name'}}) {
705 $found{$pkg{'name'}} = 1;
706 }
707 }
708 close(REPO);
709 }
710 foreach my $key (sort keys %found) {
711 print "$key\n";
712 }
713 if (not %found) {print "No matching packages found\n";};
714 }
715
716 # List all available packages ##############################################
717 sub list {
718 my $arg = $ARGV[1];
719 my %found;
720 foreach my $repo(@repos) {
721 my @r = split(/\|/, $repo);
722 my $dir = $r[0];
723 my $url = $r[1];
724 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
725 while (<REPO>) {
726 chomp;
727 my %pkg = parsepackage($_, $dir, $url, 0);
728 $found{$pkg{'name'}} = 1;
729 }
730 close(REPO);
731 }
732 foreach my $key (sort keys %found) {
733 print "$key\n";
734 }
735 }
736
737 # Show path for a package ##################################################
738 sub path {
739 my $arg = $ARGV[1];
740 foreach my $repo(@repos) {
741 my @r = split(/\|/, $repo);
742 my $dir = $r[0];
743 my $url = $r[1];
744 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
745 while (<REPO>) {
746 chomp;
747 my %pkg = parsepackage($_, $dir, $url, 0);
748 if ($pkg{'name'} eq $arg) {
749 print $pkg{'path'} . "\n";
750 close(REPO);
751 return;
752 }
753 }
754 close(REPO);
755 }
756 print "Package '$arg' not found\n";
757 }
758
759 # Show current installed version of a package ##############################
760 sub current {
761 my $pkgname = $ARGV[1];
762 getinstalled();
763 if ($installed{$pkgname}) {
764 print "$installed{$pkgname}\n";
765 } else {
766 print "Package $pkgname not installed\n";
767 }
768 }
769
770 # Print the README file for a package ######################################
771 sub readme {
772 my $arg = $ARGV[1];
773 foreach my $repo(@repos) {
774 my @r = split(/\|/, $repo);
775 my $dir = $r[0];
776 my $url = $r[1];
777 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
778 while (<REPO>) {
779 chomp;
780 my %pkg = parsepackage($_, $dir, $url, 0);
781 if ($pkg{'name'} eq $arg) {
782 printreadme(%pkg);
783 close(REPO);
784 return;
785 }
786 }
787 close(REPO);
788 }
789 print "Package '$arg' not found\n";
790 }
791
792 # Remove given packages ####################################################
793 sub remove {
794 $curraction = "removed";
795 shift(@ARGV);
796 foreach my $pkg(@ARGV) {
797 $pptasks{$pkg} = "";
798 if (system("/usr/bin/pkgrm $pkg") ==0) {
799 push(@donetasks, $pkg);
800 } else {
801 push(@failtasks, "where removal failed,$pkg");
802 }
803 }
804 printresults();
805 }
806
807 # List installed packages ##################################################
808 sub listinst {
809 getinstalled();
810 foreach my $key (sort keys %installed) {
811 print "$key\n";
812 }
813 }
814
815 # Print if package is installed ###########################################
816 sub isinst {
817 getinstalled();
818 shift(@ARGV);
819 foreach my $pkg(@ARGV) {
820 if ($installed{$pkg}) {
821 print "package $pkg is installed\n";
822 } else {
823 print "package $pkg is not installed\n";
824 }
825 }
826 }
827
828
829 # Lock given packages ######################################################
830 sub dolock {
831 shift(@ARGV);
832 foreach my $arg(@ARGV) {
833 my $found = 0;
834 foreach my $repo(@repos) {
835 if ($found == 0) {
836 my @r = split(/\|/, $repo);
837 my $dir = $r[0];
838 my $url = $r[1];
839 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
840 while (<REPO>) {
841 chomp;
842 my %pkg = parsepackagelight($_);
843 if ($pkg{'name'} eq $arg) {
844 $found = 1;
845 lockadd($arg);
846 }
847 }
848 close(REPO);
849 }
850 }
851 if ($found == 0) {print "Package '$arg' not found\n"};
852 }
853 }
854
855 # Unlock given packages ####################################################
856 sub unlock {
857 shift(@ARGV);
858 my @locked;
859 my $found;
860 foreach my $arg(@ARGV) {
861 $found = 0;
862 @locked = ();
863 open(LCK, $LOCKFILE) or exiterr("could not open lock file");
864 while (<LCK>) {
865 chomp;
866 if ($_ eq $arg) {
867 push (@locked, "-");
868 $found = 1;
869 } else {
870 push (@locked, $_);
871 }
872 }
873 close(LCK);
874 if ($found == 1) {
875 @locked = sort(@locked);
876 open(LCK, ">$LOCKFILE") or exiterr("could not write to lock file");
877 foreach my $lock(@locked) {
878 if ($lock ne "-") {print LCK "$lock\n"};
879 }
880 close(LCK);
881 } else {
882 print "Not locked previously: $arg\n";
883 }
884 }
885 }
886
887 # List locked packages #####################################################
888 sub listlocked {
889 open(LCK, $LOCKFILE)
890 or exit;
891 while (<LCK>) {
892 chomp;
893 print "$_\n";
894 }
895 close(LCK);
896 }
897
898 # Print formatted info #####################################################
899 sub doprintf {
900 my %found;
901 foreach my $repo(@repos) {
902 my @r = split(/\|/, $repo);
903 my $dir = $r[0];
904 my $url = $r[1];
905 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
906 while (<REPO>) {
907 chomp;
908 my %pkg;
909 if (index($ARGV[1], "%i") >=0 ) {
910 %pkg = parsepackage($_, $dir, $url, 1);
911 } else {
912 %pkg = parsepackage($_, $dir, $url, 0);
913 }
914 if (not $found{$pkg{'name'}}) {
915 if ($filter ne "") {
916 my $match = $pkg{'name'};
917 my $cfilter = $filter;
918 $cfilter =~ s/\*/\.\*/;
919 if ($match =~ /^$cfilter$/) {
920 formattedprint(%pkg);
921 $found{$pkg{'name'}} = 1;
922 }
923 } else {
924 formattedprint(%pkg);
925 $found{$pkg{'name'}} = 1;
926 }
927 }
928 }
929 close(REPO);
930 }
931 }
932
933 # Show differences between installed and available packages ################
934 sub diff {
935 my %found;
936 my $gotdiff = 0;
937 foreach my $repo(@repos) {
938 my @r = split(/\|/, $repo);
939 my $dir = $r[0];
940 my $url = $r[1];
941 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
942 while (<REPO>) {
943 chomp;
944 my %pkg;
945 %pkg = parsepackage($_, $dir, $url, 1);
946 if (not $found{$pkg{'name'}}) {
947 if ($pkg{'instversion'}) {
948 if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'}) {
949 if (islocked($pkg{'name'}) eq "no") {
950 if ($gotdiff == 0){
951 print "Differences between installed packages and packages repo:\n\n";
952 printf("%-19s %-19s %-19s\n\n","Package","Installed","Available in the repositories");
953 $gotdiff = 1;
954 }
955 printf("%-19s %-19s %-19s\n", $pkg{'name'}, $pkg{'instversion'}, $pkg{'version'}."-".$pkg{'release'});
956 } elsif ($all) { # yeah, it blows, at least avoid to read the locked state twice.
957 if ($gotdiff == 0){
958 print "Differences between installed packages and packages repo:\n\n";
959 printf("%-19s %-19s %-19s\n\n","Package","Installed","Available in the repositories");
960 $gotdiff = 1;
961 }
962 printf("%-19s %-19s %-19s %-19s\n", $pkg{'name'}, $pkg{'instversion'}, $pkg{'version'}."-".$pkg{'release'}, "locked");
963 }
964 }
965 }
966 $found{$pkg{'name'}} = 1;
967 }
968 }
969 close(REPO);
970 }
971 if ($gotdiff ==0) {print "No differences found\n"};
972 }
973
974 # Show differences between installed and available packages ################
975 sub quickdiff {
976 my %found;
977 my $gotdiff = 0;
978 foreach my $repo(@repos) {
979 my @r = split(/\|/, $repo);
980 my $dir = $r[0];
981 my $url = $r[1];
982 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
983 while (<REPO>) {
984 chomp;
985 my %pkg;
986 %pkg = parsepackage($_, $dir, $url, 1);
987 if (not $found{$pkg{'name'}}) {
988 if ($pkg{'instversion'}) {
989 if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and islocked($pkg{'name'}) eq "no") {
990 if ($gotdiff == 0){
991 print $pkg{'name'};
992 $gotdiff = 1;
993 } else {
994 print " " . $pkg{'name'};
995 }
996 }
997 }
998 $found{$pkg{'name'}} = 1;
999 }
1000 }
1001 close(REPO);
1002 }
1003 if ($gotdiff != 0) {print "\n"};
1004 }
1005
1006 # Display duplicate packages (found in more than one repo) #################
1007 sub dup {
1008 my %found;
1009 foreach my $repo(@repos) {
1010 my @r = split(/\|/, $repo);
1011 my $dir = $r[0];
1012 my $url = $r[1];
1013 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
1014 while (<REPO>) {
1015 chomp;
1016 my %pkg;
1017 %pkg = parsepackage($_, $dir, $url, 0);
1018 $found{$pkg{'name'}} .= "###" . $pkg{'path'}."/". $pkg{'name'}.$pkg{'version'}."-".$pkg{'release'};
1019 }
1020 close(REPO);
1021 }
1022 my $curr = "";
1023 foreach my $key (sort keys %found) {
1024 my $value = $found{$key};
1025 $value =~ s/^\#\#\#//;
1026 if (rindex($value, "###") >=0){
1027 print "* $key\n";
1028 my @d = split(/\#\#\#/, $value);
1029 foreach my $dup(@d){
1030 print " $dup\n";
1031 }
1032 }
1033 }
1034 }
1035
1036 # Show list of dependencies for package ####################################
1037 sub depends {
1038 getdependencies($ARGV[1], 1, "") or exiterr("package '$ARGV[1]' not found");
1039 if (@dependencies) {print "-- dependencies ([i] = installed, [u] = updatable)\n"}
1040 foreach my $dep(@dependencies) {
1041 print "$dep\n";
1042 }
1043 if (%missingdeps) {
1044 print "\n-- missing packages\n";
1045 foreach my $dep(sort keys %missingdeps) {
1046 print "$dep from $missingdeps{$dep}\n";
1047 }
1048 }
1049 }
1050
1051 # Show compact list of dependencies for package ############################
1052 sub quickdep {
1053 getdependencies($ARGV[1], 0, "") or exiterr("package '$ARGV[1]' not found");
1054 foreach my $dep(@dependencies) {
1055 print "$dep ";
1056 }
1057 print "\n";
1058 }
1059
1060 # Show packages directly depending from given package ######################
1061 sub dependent {
1062 my $arg = $ARGV[1];
1063 my %dp;
1064 if (not $all) { getinstalled(); }
1065 foreach my $repo(@repos) {
1066 my @r = split(/\|/, $repo);
1067 my $dir = $r[0];
1068 my $url = $r[1];
1069 open(DEPS, "$dir/PKGDEPS")
1070 or exiterr("could not open $dir/PKGDEPS");
1071 while (<DEPS>) {
1072 chomp;
1073 my $dep = $_;
1074 $dep =~ s/\s+\:.*$//;
1075 s/^.*\: /\,/;
1076 s/$/\,\$/;
1077 if ( /\,\Q$arg\E\,/ ) {
1078 if (not $all) {
1079 if ($installed{$dep}) {
1080 $dp{$dep} = 1;
1081 }
1082 } else {
1083 $dp{$dep} = 1;
1084 }
1085 }
1086 }
1087 close(DEPS);
1088 }
1089 foreach my $res(keys %dp) {
1090 print "$res\n";
1091 }
1092 }
1093
1094 # Install given package ####################################################
1095 sub install {
1096 $curraction = "installed";
1097 my @args = @_; shift(@args);
1098 getinstalled();
1099 foreach my $pkgname(@args) {
1100 my %pkg = getpackage($pkgname, 1);
1101 if (not %pkg) {
1102 push(@failtasks, "not found,$pkgname");
1103 } elsif (getshortstatus(%pkg) ne "[ ]") {
1104 push(@prevtasks, "$pkgname");
1105 } elsif (downloadpkg(%pkg) and installpkg("", %pkg)) {
1106 push(@donetasks, $pkgname);
1107 } else {
1108 push(@failtasks, "where install failed,$pkgname");
1109 }
1110 }
1111 printresults();
1112 }
1113
1114 # Update given package #####################################################
1115 sub update {
1116 $curraction = "updated";
1117 my @args = @_; shift(@args);
1118 getinstalled();
1119 foreach my $pkgname(@args) {
1120 my %pkg = getpackage($pkgname, 1);
1121 if (not %pkg) {
1122 push(@failtasks, "not found,$pkgname");
1123 } elsif (getshortstatus(%pkg) eq "[ ]") {
1124 push(@prevtasks, "$pkgname");
1125 } elsif (downloadpkg(%pkg) and installpkg("-u ", %pkg)) {
1126 push(@donetasks, $pkgname);
1127 } else {
1128 push(@failtasks, "where update failed,$pkgname");
1129 }
1130 }
1131 printresults();
1132 }
1133
1134 # Update out of date packages ##############################################
1135 sub sysup {
1136 my %found;
1137 my @diff;
1138 foreach my $repo(@repos) {
1139 my @r = split(/\|/, $repo);
1140 my $dir = $r[0];
1141 my $url = $r[1];
1142 open(REPO, "$dir/PKGREPO") or exiterr("could not open $dir/PKGREPO");
1143 while (<REPO>) {
1144 chomp;
1145 my %pkg;
1146 %pkg = parsepackage($_, $dir, $url, 1);
1147 if (not $found{$pkg{'name'}}) {
1148 if ($pkg{'instversion'}) {
1149 if ($pkg{'instversion'} ne $pkg{'version'}."-".$pkg{'release'} and islocked($pkg{'name'}) eq "no") {
1150 push(@diff, $pkg{'name'});
1151 }
1152 }
1153 $found{$pkg{'name'}} = 1;
1154 }
1155 }
1156 close(REPO);
1157 }
1158 if (@diff) {
1159 unshift(@diff, "dummy"); # is shifted later in update sub;
1160 update(@diff);
1161 }
1162 }
1163
1164 sub depinst {
1165 my @toinst; my %seen;
1166 $curraction = "installed";
1167 my @args = @ARGV; shift(@args);
1168 getinstalled();
1169 foreach my $pkgname(@args) {
1170 getdependencies($pkgname, 0, "");
1171 foreach my $dep(@dependencies) {
1172 if (not $seen{$dep}) {
1173 my %pkg = getpackage($dep, 1);
1174 if (%pkg) {
1175 if (getshortstatus(%pkg) eq "[ ]"){
1176 push(@toinst, $pkg{'name'});
1177 }
1178 }
1179 $seen{$dep} = 1;
1180 }
1181 }
1182 }
1183 if (@toinst) {
1184 unshift(@toinst, "dummy"); # is shifted later in install sub;
1185 install(@toinst);
1186 }
1187 }
|