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