summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile33
-rw-r--r--README-autoirpm-icons3
-rwxr-xr-x_irpm73
-rw-r--r--autoirpm.843
-rw-r--r--autoirpm.README48
-rw-r--r--autoirpm.deny3
-rw-r--r--autoirpm.uninstall23
-rw-r--r--autoirpm.update36
-rw-r--r--autoirpm.update-all.cc72
-rw-r--r--gurpmi7
-rw-r--r--po/Makefile21
-rw-r--r--po/fr.po82
-rw-r--r--po/urpmi.pot85
-rw-r--r--rpm-find-leaves7
-rwxr-xr-xurpmi246
-rw-r--r--urpmi.884
-rwxr-xr-xurpmi.addmedia127
-rw-r--r--urpmi.addmedia.886
-rw-r--r--urpmi.removemedia.855
19 files changed, 1134 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..43b8cab8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+PREFIX =
+BINDIR = $(PREFIX)/usr/bin
+MANDIR = $(PREFIX)/usr/man
+SBINDIR = $(PREFIX)/usr/sbin
+XBINDIR = $(PREFIX)/usr/X11R6/bin
+URPMIDIR = $(PREFIX)/etc/urpmi
+LOCALEDIR = $(PREFIX)/usr/share/locale
+
+
+.PHONY: install
+
+install: autoirpm.update-all
+ $(MAKE) -C po $@
+ install -d $(BINDIR) $(SBINDIR) $(XBINDIR) $(URPMIDIR) $(MANDIR)/man8
+ install -m 4755 urpmi $(BINDIR)
+ install _irpm rpm-find-leaves $(BINDIR)
+ install -m 644 autoirpm.deny $(URPMIDIR)
+ for i in *.8; do bzip2 -c $$i > $(MANDIR)/man8/$$i.bz2 ; done
+ install urpmi.addmedia autoirpm.update autoirpm.uninstall $(SBINDIR)
+ install -s autoirpm.update-all $(SBINDIR)
+ ln -sf urpmi.addmedia $(SBINDIR)/urpmi.removemedia
+ ln -sf urpmi.addmedia $(SBINDIR)/urpmi.update
+ install gurpmi $(XBINDIR)
+
+autoirpm.update-all: %: %.cc
+ $(CXX) -I/usr/include/rpm -g $< -lrpm -ldb1 -lz -o $@
+
+po:
+ $(MAKE) -C $@
+
+clean:
+ $(MAKE) -C po $@
+ rm -f *~ autoirpm.update-all
diff --git a/README-autoirpm-icons b/README-autoirpm-icons
new file mode 100644
index 00000000..9216a31a
--- /dev/null
+++ b/README-autoirpm-icons
@@ -0,0 +1,3 @@
+This package is to be used with autoirpm package.
+It provides menu icons for non installed apps that should take advantages of
+autoirpm features.
diff --git a/_irpm b/_irpm
new file mode 100755
index 00000000..a51f69e3
--- /dev/null
+++ b/_irpm
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+
+$automatic = 0;
+$timeout = 15;
+
+$DIR = "/etc/urpmi";
+$BASE = "$DIR/autoirpm";
+$INSTALL_SCRIPT_REP = "$BASE.scripts";
+
+($lang) = ($ENV{LC_ALL} || $ENV{LANGUAGE} || $ENV{LC_MESSAGES} || $ENV{LANG}) =~ /(..)/;
+
+
+$rpm = shift @ARGV;
+print STDERR "autoirpm: ", i18n("installing"), " $rpm\n";
+
+`xtest`;
+$X = ($? == 0);
+
+my $pid;
+$SIG{ALRM} = sub { $pid and kill 9, $pid; not_found(); };
+alarm $timeout;
+
+if (!$automatic) {
+ $interactive_mesg = i18n("Automatic installation of packages...\nYou requested installation of package") . " $rpm\n" . i18n("Is it ok?");
+ if ($X) {
+ my $ok = i18n("Ok");
+ my $cancel = i18n("Cancel");
+ ($pid = fork) or exec "gmessage", "-default", $ok, "-buttons", "$ok:0,$cancel:2", $interactive_mesg;
+ wait();
+ $? and not_found();
+ } else {
+ use POSIX;
+ if (isatty(0)) {
+ print $interactive_mesg, " (y/n) ";
+ <STDIN> =~ /y/i or not_found();
+ } else {
+ # Arghhh not in automatic and no way to contact the user... dying
+ not_found();
+ }
+ }
+}
+alarm 0;
+
+$urpmi = !$automatic && $X ? "gurpmi" : "urpmi";
+fork or exec $urpmi, "--comment", $ARGV[0], $rpm; wait;
+
+# launch the initial prog
+(readlink $ARGV[0]) !~ /$INSTALL_SCRIPT_REP/ and exec @ARGV;
+
+not_found();
+
+sub not_found {
+ print STDERR "$rpm: command not found\n";
+ exit 127;
+}
+sub i18n { $I18N{$lang}->{$_[0]} || $_[0]; }
+
+
+BEGIN {
+
+%I18N = (
+
+'fr' => {
+"installing", "installation de",
+"Automatic installation of packages...\nYou requested installation of package" => "Installation automatique des packages...\nVous avez demandé l'installation du package",
+"Is it ok?" => "On continue ?",
+"Ok" => "Continuer",
+"Cancel" => "Annuler",
+},
+
+);
+
+}
diff --git a/autoirpm.8 b/autoirpm.8
new file mode 100644
index 00000000..949c6afb
--- /dev/null
+++ b/autoirpm.8
@@ -0,0 +1,43 @@
+.TH autoirpm 8 "22 Nov 1999" "Mandrakesoft" "Linux-Mandrake"
+.IX autoirpm
+.SH NAME
+autoirpm \- auto installs the RPM matching your command
+.SH SYNOPSIS
+.B autoirpm
+.SH DESCRIPTION
+autoirpm *magically* guesses which package you need and installs it. Let's imagine that you typed gmix to launch your sound mixer. If it is not available, you are then asked if you wish to install the package gnome-media which contains the gmix binary...
+.PP
+To do so, launch autoirpm.update-all, which scans all packages known by urpmi for all binary executables. It then creates links in respective binary directories...
+Use autoirpm.uninstall to remove all links created by autoirpm.update.
+.PP
+use \fBautoirpm.update <name>\fP to update executables contained in packages of <name>d media.
+.PP
+use \fBautoirpm.update-all\fP to update executables contained in packages of all medias known by urpmi.
+.PP
+use \fBautoirpm.uninstall\fP to remove all links installed by autoirpm.
+.PP
+This feature may be offered for menu icons installing autoirpm-icons package.
+.SH FILES
+/etc/urpmi/autoirpm.deny
+.br
+All binaries contained in packages listed in this file won't lead to an auto install of rpm.
+.PP
+/etc/urpmi/autoirpm.allow
+.br
+If present, only binaries of listed packages will offer the feature of auto-install.
+
+.SH "SEE ALSO"
+urpmi(8)
+.SH AUTHOR
+Pascal Rigaux, Mandrakesoft
+.br
+pixel@mandrakesoft.com
+
+
+
+
+
+
+
+
+
diff --git a/autoirpm.README b/autoirpm.README
new file mode 100644
index 00000000..61e2afa0
--- /dev/null
+++ b/autoirpm.README
@@ -0,0 +1,48 @@
+* BUG
+
+emacs with xemacs causes pbs 'cuz same binaries.
+
+List of packages not to autoinstall:
+- psacct
+- the one containing netscape (just a wrapper)
+
+
+ALL BELOW IS MAYBE OBSOLETE
+
+
+The idea is to auto-install rpms on demand, when needed. For this, every
+possible binaries that could exist (eg: /usr/bin/gimp, apropos shouldn't that be
+/usr/X11R6/bin?) is created as a symlink to a script for installing the needed
+packages. Not every package should be auto-installable.
+
+For the moment, it is very tied to a distribution. The package i've done is for
+the mandrake-5.3, using another distribution could result in???
+The package is auto-generated given the different packages which will be
+auto-installable.
+
+Advantages: it seems like you're having every packages installed, but without
+consuming unneeded harddisk space. So if you never use gimp, it doesn't change
+anything. The first time you call gimp, the package is installed (with the
+needed required packages).
+
+Bad points: security?
+
+
+INSTALLATION:
+* rpm -i autoirpm-???.rpm
+* optional (by default it takes /mnt/cdrom):
+ edit /etc/autoirpm/files to give the location of the rpms
+* execute /usr/sbin/autoirpm-update
+
+TODO:
+* links to progs are not autoinstalled
+* automatic uninstall of unused packages :) (cron here)
+* add an interactive mode (term, X...).
+* maybe pb with ENV variables not completly the same (eg: "ksh" is not the same as "sh -c ksh")??
+* dependencies' versions
+* wrapper around rpm needed (call autoirpm-install.pm on rpm -e)
+
+FUTURE:
+* patch the kernel, so that if the open(2) (or maybe stat...) call fail, a
+script is called that install the needed file. Interesting for headers (.h),
+librairies (.so), man pages :)))) (crazy idea, but...)
diff --git a/autoirpm.deny b/autoirpm.deny
new file mode 100644
index 00000000..9f8e56e4
--- /dev/null
+++ b/autoirpm.deny
@@ -0,0 +1,3 @@
+gdm
+quotaon quotaoff
+linux_logo
diff --git a/autoirpm.uninstall b/autoirpm.uninstall
new file mode 100644
index 00000000..d0483a03
--- /dev/null
+++ b/autoirpm.uninstall
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+
+$DIR = "/etc/urpmi";
+$BASE = "$DIR/autoirpm";
+$AUTO_INSTALL_BIN_LIST = "$BASE.binaries";
+$INSTALL_SCRIPT_REP = "$BASE.scripts";
+
+open F, $AUTO_INSTALL_BIN_LIST or die;
+map { chop; remove_links_and_scripts($_) } <F>;
+close F;
+
+sub remove_links_and_scripts($) {
+ my ($rpm, @progs) = split;
+
+ my $script = "$INSTALL_SCRIPT_REP/$rpm";
+
+ -e $script or return 0; # not installed for this package
+ foreach (<@progs>) {
+ readlink "/$_" ne $script and next;
+ unlink "/$_" or warn "removing $_ failed";
+ }
+ unlink $script or warn "removing $script failed";
+}
diff --git a/autoirpm.update b/autoirpm.update
new file mode 100644
index 00000000..3dfff948
--- /dev/null
+++ b/autoirpm.update
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+$DIR = "/etc/urpmi";
+$BASE = "$DIR/autoirpm";
+$AUTO_INSTALL_BIN_LIST = "$BASE.binaries";
+$INSTALL_SCRIPT_REP = "$BASE.scripts";
+
+system("autoirpm.update-all $BASE.allow $BASE.deny $DIR/hdlist.* > $AUTO_INSTALL_BIN_LIST");
+$? == 0 or die "autoirpm.upgrade-all failed\n";
+
+open F, $AUTO_INSTALL_BIN_LIST or die;
+map { chop; create_links_and_install_scripts($_) } <F>;
+close F;
+
+sub create_links_and_install_scripts($) {
+ my ($rpm, @progs) = split ' ', $_[0];
+ my $script = "$INSTALL_SCRIPT_REP/$rpm";
+
+ foreach (@progs) { lstat "/$_" and return } # verify that it's not installed
+
+ foreach (@progs) {
+ make_dirname("/$_");
+ symlink $script, "/$_"; # or die "$rpm: /$_";
+ }
+
+ open G, ">$script" or die;
+ print G "_irpm $rpm \$0 \$*\n";
+ close G;
+ chmod 0755, "$script";
+}
+
+sub make_dirname($) {
+ my $file = $_[0];
+ my $dir = `dirname $file`;
+ `mkdir -p $dir 2>/dev/null`;
+}
diff --git a/autoirpm.update-all.cc b/autoirpm.update-all.cc
new file mode 100644
index 00000000..db2ee5a2
--- /dev/null
+++ b/autoirpm.update-all.cc
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <rpmlib.h>
+#include <string>
+#include <set>
+#include <fstream>
+
+
+typedef set<string>::difference_type diff_type;
+
+set<string> *read_set(const char *file) {
+ ifstream input(file);
+ if (input) {
+ set<string> *myset = new set<string>;
+ istream_iterator<string,diff_type> input_set(input),eos;
+ copy(input_set, eos, inserter(*myset, myset->begin()));
+ return myset;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ if (argc <= 3) {
+ cerr << "usage: " << argv[0] << " <allow progs file> <deny progs file> <hdlist> [<hdlist> ...]\n";
+ exit(1);
+ }
+
+ set<string> *allow = read_set(argv[1]);
+ set<string> *deny = read_set(argv[2]);
+
+ for (int i = 3; i < argc; i++) {
+ Header header;
+ FD_t fd = fdOpen(argv[i], O_RDONLY, 0);
+ if (fdFileno(fd) < 0) {
+ fprintf(stderr, "%s: cannot open file %s\n", argv[0], argv[i]);
+ exit(1);
+ }
+
+ while ((header=headerRead(fd, HEADER_MAGIC_YES))) {
+ int_32 type, count;
+ unsigned short *p;
+ char **f, *name, *s;
+ int printed = 0;
+
+ headerGetEntry(header, RPMTAG_NAME, &type, (void **) &name, &count);
+ headerGetEntry(header, RPMTAG_FILEMODES, &type, (void **) &p, &count);
+ headerGetEntry(header, RPMTAG_FILENAMES, &type, (void **) &f, &count);
+ for (; count--; *p++, *f++)
+ if ((*p & 040111) == 0111 &&
+ (s = strrchr(*f, '/')) &&
+ s - 3 >= *f &&
+ strncmp(s - 3, "bin", 3) == 0 &&
+ (!allow || allow->count(s + 1)) &&
+ (!deny || !deny->count(s + 1))) {
+
+ if (!printed) {
+ printed = 1;
+ cout << name;
+ }
+ cout << " " << *f;
+ }
+ if (printed) cout << "\n";
+ }
+ fdClose(fd);
+ }
+ return 0;
+}
diff --git a/gurpmi b/gurpmi
new file mode 100644
index 00000000..f36525f0
--- /dev/null
+++ b/gurpmi
@@ -0,0 +1,7 @@
+#!/usr/bin/perl
+
+$ENV{XAUTHORITY} or $ENV{XAUTHORITY} = "$ENV{HOME}/.Xauthority";
+
+
+exec "urpmi", "--X", @ARGV;
+
diff --git a/po/Makefile b/po/Makefile
new file mode 100644
index 00000000..5005a700
--- /dev/null
+++ b/po/Makefile
@@ -0,0 +1,21 @@
+POFILES = $(shell ls *.po)
+LOCALEDIR = $(PREFIX)/usr/share/locale
+
+all: $(POFILES)
+
+install: $(POFILES)
+ for i in $(POFILES:%.po=%); do \
+ install -d $(LOCALEDIR)/$$i/LC_MESSAGES ; \
+ cp -f $$i.po $(LOCALEDIR)/$$i/LC_MESSAGES/urpmi.po ; \
+ done
+
+clean:
+ rm -f messages empty.po $(POFILES:%=%t)
+
+$(POFILES): urpmi.pot
+ cp -f $@ $@t
+ msgmerge $@t $< > $@
+ rm $@t
+
+urpmi.pot: ../urpmi
+ xgettext -L C -F -n --keyword=_ -o $@ $<
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 00000000..f9dfde13
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,82 @@
+# Translation file of urpmi
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: urpmi VERSION\n"
+"POT-Creation-Date: 1999-12-11 01:11+0100\n"
+"PO-Revision-Date: 1999-08-25 11:07+0200\n"
+"Last-Translator: pixel@mandrakesoft.com\n"
+"Language-Team: french\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../urpmi:62
+#, c-format
+msgid "no package named %s\n"
+msgstr "pas de package %s\n"
+
+#: ../urpmi:63
+#, c-format
+msgid "The following packages contain %s: %s\n"
+msgstr "Voici les différents packages contenant %s: %s\n"
+
+#: ../urpmi:70
+msgid "rpm database query failed\n"
+msgstr "erreur lors de la consultation de la base données\n"
+
+#: ../urpmi:79
+msgid "The following packages are going to be installed"
+msgstr "Les packages suivants vont être installés"
+
+#: ../urpmi:80
+msgid "Is it ok?"
+msgstr "On continue ?"
+
+#: ../urpmi:83
+msgid "Ok"
+msgstr "Continuer"
+
+#: ../urpmi:84
+msgid "Cancel"
+msgstr "Annuler"
+
+#: ../urpmi:120
+#, c-format
+msgid "Please insert the %s named %s"
+msgstr "Veuillez insérer le %s %s"
+
+#: ../urpmi:122
+msgid "Press enter when it's done..."
+msgstr "Ensuite appuyez sur <<Enter>>"
+
+#: ../urpmi:127
+#, c-format
+msgid "Sorry can't find file %s, exiting"
+msgstr "Désolé impossible de trouver le fichier %s"
+
+#: ../urpmi:135
+msgid "everything already installed"
+msgstr "tout est déja installé"
+
+#: ../urpmi:141
+#, c-format
+msgid "installing %s\n"
+msgstr "installation de %s\n"
+
+#: ../urpmi:144
+msgid "Installation failed"
+msgstr "Erreur lors de l'installation"
+
+#: ../urpmi:173
+msgid "One of the following packages is needed:"
+msgstr "Un des packages suivants est nécessaire :"
+
+#: ../urpmi:182
+#, c-format
+msgid "What is your choice? (1-%d) "
+msgstr "Lequel choisissez-vous ? (1-%d)"
+
+#: ../urpmi:185
+msgid "Sorry, bad choice, try again\n"
+msgstr "Désolé, mauvais choix, veuillez réessayez\n"
diff --git a/po/urpmi.pot b/po/urpmi.pot
new file mode 100644
index 00000000..9e2f8e34
--- /dev/null
+++ b/po/urpmi.pot
@@ -0,0 +1,85 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 1999-12-11 04:18+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: ../urpmi:62
+#, c-format
+msgid "no package named %s\n"
+msgstr ""
+
+#: ../urpmi:63
+#, c-format
+msgid "The following packages contain %s: %s\n"
+msgstr ""
+
+#: ../urpmi:70
+msgid "rpm database query failed\n"
+msgstr ""
+
+#: ../urpmi:79
+msgid "The following packages are going to be installed"
+msgstr ""
+
+#: ../urpmi:80
+msgid "Is it ok?"
+msgstr ""
+
+#: ../urpmi:83
+msgid "Ok"
+msgstr ""
+
+#: ../urpmi:84
+msgid "Cancel"
+msgstr ""
+
+#: ../urpmi:120
+#, c-format
+msgid "Please insert the %s named %s"
+msgstr ""
+
+#: ../urpmi:122
+msgid "Press enter when it's done..."
+msgstr ""
+
+#: ../urpmi:127
+#, c-format
+msgid "Sorry can't find file %s, exiting"
+msgstr ""
+
+#: ../urpmi:135
+msgid "everything already installed"
+msgstr ""
+
+#: ../urpmi:141
+#, c-format
+msgid "installing %s\n"
+msgstr ""
+
+#: ../urpmi:144
+msgid "Installation failed"
+msgstr ""
+
+#: ../urpmi:173
+msgid "One of the following packages is needed:"
+msgstr ""
+
+#: ../urpmi:182
+#, c-format
+msgid "What is your choice? (1-%d) "
+msgstr ""
+
+#: ../urpmi:185
+msgid "Sorry, bad choice, try again\n"
+msgstr ""
diff --git a/rpm-find-leaves b/rpm-find-leaves
new file mode 100644
index 00000000..30f3f2f1
--- /dev/null
+++ b/rpm-find-leaves
@@ -0,0 +1,7 @@
+#!/usr/bin/perl
+
+$r = join '|', map { chop; $l{$_} = 1; quotemeta } `rpm -qa --queryformat "%{NAME}\n"`;
+$R = qr/ $r/;
+open F, "/etc/urpmi/depslist" or die "can't find depslist\n";
+$R && /(\S+)-[^-]+-[^-]+ / && delete $l{$1} foreach <F>;
+print "$_\n" foreach keys %l;
diff --git a/urpmi b/urpmi
new file mode 100755
index 00000000..84c282cc
--- /dev/null
+++ b/urpmi
@@ -0,0 +1,246 @@
+#!/usr/bin/perl -U
+
+my $lang = $ENV{LC_ALL} || $ENV{LANGUAGE} || $ENV{LC_MESSAGES} || $ENV{LANG};
+load_po(substr($lang, 0, 2));
+
+$ENV{PATH} = "/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin";
+$< = $>;
+
+
+open LOG, ">>/var/log/urpmi.log" or die;
+print LOG scalar localtime, " urpmi called with @ARGV\n";
+close LOG;
+
+if (@ARGV and $ARGV[0] eq '--auto') {
+ $auto = 1;
+ shift @ARGV;
+}
+
+if (@ARGV and $ARGV[0] eq '--X') {
+ $X = 1;
+ shift @ARGV;
+}
+
+while (@ARGV and $ARGV[0] eq '--comment') {
+ shift @ARGV;
+ shift @ARGV;
+}
+
+@ARGV or die "usage: urpmi [--auto] package_name [package_names...]\n";
+
+$dir = "/etc/urpmi";
+$depsfile = "$dir/depslist";
+$rpmlistfiles = "$dir/list.*";
+
+open SAVEOUT, ">&STDOUT";
+open SAVEERR, ">&STDERR";
+open STDOUT, "|tee -a /var/log/urpmi.installed" or die;
+open STDERR, "|tee -a /var/log/urpmi.log" or die;
+select STDERR; $| = 1; # make unbuffered
+select STDOUT; $| = 1; # make unbuffered
+
+open F, $depsfile or die();
+foreach (<F>) {
+ my ($pack, $deps) = /(\S+)\s+\S+\s+(.*)/ or die("urpmi: bad format file $depsfile\n");
+ $deps{$pack} = [ split ' ', $deps ];
+
+ foreach $v (@ARGV) {
+ $_ = quotemeta $v;
+ $pack =~ /^$_-[^-]+-[^-]+$/ and $exact{$v} = $pack;
+ $pack =~ /^$_-[^-]+$/ and $exact{$v} = $pack;
+ $pack =~ /^$_$/ and $exact{$v} = $pack;
+ $pack =~ /$_/ and push @{$found{$v}}, $pack;
+ $pack =~ /$_/i and push @{$foundi{$v}}, $pack;
+ }
+}
+close F or die();
+
+my $ok = 1;
+foreach (@ARGV) {
+ my $pack = $exact{$_};
+ unless ($pack) {
+ my $l = $found{$_}; $l or $l = $foundi{$_};
+ if (@$l == 0) { warn(_("no package named %s\n", $_)); $ok = 0; }
+ elsif (@$l > 1) { warn(_("The following packages contain %s: %s\n", $_, join(', ', @$l))); $ok = 0; }
+ $pack = $$l[0];
+ }
+ push @packages, $pack;
+}
+$ok or exit 1;
+
+@installed = `/bin/rpm -qa`; $? and die(_("rpm database query failed\n"));
+foreach (@installed) {
+ my ($name, $v, $r) = /(.*)-([^-]+)-([^-.]+)/;
+ exists $installed{$name} && le_version([$v, $r], $installed{$name}) or $installed{$name} = [$v, $r];
+}
+@installed{map { chop; $_ } @installed} = ();
+my %to_install; closure_deps(\%to_install, @packages); @to_install = keys %to_install;
+
+if (!$auto and difference2(\@to_install, \@packages)) {
+ my $msg = _("To satisfy dependencies, the following packages are going to be installed");
+ my $msg2 = _("Is it ok?");
+ if ($X) {
+ my $p = join "\n", @to_install;
+ my $ok = _("Ok");
+ my $cancel = _("Cancel");
+ `gmessage -default $ok -buttons "$ok:0,$cancel:2" "$msg:\n$p\n\n$msg2"`;
+ $? and exit 0;
+ } else {
+ print SAVEOUT "$msg:\n@to_install\n$msg2 (y/n) ";
+ <STDIN> =~ /y/i or exit 0;
+ }
+}
+
+$to_install = join '|', map { quotemeta($_) } @to_install;
+
+foreach $file (glob($rpmlistfiles)) {
+ open F, $file or die("urpmi: error opening $file\n");
+ $file =~ s|.*/list\.(.*?)|$1|;
+ foreach (<F>) { chop; m|/($to_install)| and $long{$1} = $_, $name{$1} = $file; }
+ close F;
+}
+foreach $l (@to_install) {
+ local $_ = $long{$l} or die("urpmi: package $l is not available\n");
+ if (s|removable_(\w+)_(\d*):/||) {
+ my $n = "$2-$name{$l}";
+ $removables{$n}->{name} = $name{$l};
+ $removables{$n}->{device} = $1;
+ push @{$removables{$n}->{list}}, $_;
+ } else {
+ s|^file:/||;
+ push @to_install_long, $_;
+ }
+}
+
+foreach (sort keys %removables) {
+ my $f = @{$removables{$_}->{list}}[0];
+ my $dev = $removables{$_}->{device};
+ `mount /dev/$dev 2>/dev/null`;
+ unless (-e $f) {
+ `umount /dev/$dev 2>/dev/null ; eject $dev 2>/dev/null`;
+ message(_("Please insert the %s named %s", $removables{$_}->{device}, $removables{$_}->{name}));
+ unless ($X) {
+ print SAVEOUT _("Press enter when it's done...");
+ <STDIN>;
+ }
+ `mount /dev/$dev 2>/dev/null`;
+ unless (-e $f) {
+ message(_("Sorry can't find file %s, exiting", $f));
+ exit 1;
+ }
+ }
+ install(@{$removables{$_}->{list}});
+}
+
+install(@to_install_long);
+$something_was_installed or message(_("everything already installed"));
+
+sub install {
+ @_ or return;
+
+ $something_was_installed = 1;
+ print SAVEOUT _("installing %s\n", join(' ', @_));
+ print scalar localtime, " @_\n";
+ $X ? `grpmi @_` : `rpm -U @_`;
+ $? and message(_("Installation failed")), exit 1;
+}
+
+# uses @deps and @installed
+sub closure_deps {
+ my $to_install = shift;
+ foreach (@_) {
+ exists $to_install->{$_} and next;
+ my ($name, $v, $r) = /(.*)-([^-]+)-([^-.]+)/;
+ exists $installed{$name} && le_version([$v, $r], $installed{$name}) and next;
+
+ $to_install->{$_} = undef;
+ my @d = @{$deps{$_}} or return $_;
+ up: foreach (@d) {
+ my %l;
+ foreach (split '\|') {
+ exists $to_install->{$_} and next up;
+ my ($name, $v, $r) = /(.*)-([^-]+)-([^-.]+)/;
+ if (exists $installed{$name}) {
+ le_version([$v, $r], $installed{$name}) and next up;
+ %l = ($name => [$v, $r]);
+ last;
+ }
+ $l{$name} = [$v, $r] unless $l{$name} && le_version([$v, $r], $l{$name});
+ }
+ my ($l) = my @l = map { "$_-$l{$_}[0]-$l{$_}[1]" } keys %l;
+
+ if (@l > 1 && !$auto) {
+ $msg = _("One of the following packages is needed:");
+ my $n;
+ if ($X) {
+ `gchooser "$msg" @l`;
+ $n = $? >> 8 || die;
+ } else {
+ print SAVEOUT "$msg\n";
+ my $i = 0; foreach (@l) { print SAVEOUT " ", ++$i, "- $_\n"; }
+ while (1) {
+ print SAVEOUT _("What is your choice? (1-%d) ", $i);
+ $n = <STDIN>;
+ 1 <= $n && $n <= $i and last;
+ print SAVEOUT _("Sorry, bad choice, try again\n");
+ }
+ }
+ $l = $l[$n - 1];
+ }
+ closure_deps($to_install, $l);
+ }
+ }
+}
+
+#- compare a version string.
+sub version_compare {
+ my ($a, $b) = @_;
+ local $_;
+
+ while ($a && $b) {
+ my ($sb, $sa) = map { $1 if $a =~ /^\W*\d/ ? s/^\W*0*(\d+)// : s/^\W*(\D+)// } ($b, $a);
+ $_ = length($sa) cmp length($sb) || $sa cmp $sb and return $_;
+ }
+}
+sub le_version {
+ my $cmp = version_compare($_[0][0], $_[1][0]);
+ return $cmp < 0 || $cmp == 0 && version_compare($_[0][1], $_[1][1]) < 0;
+}
+
+
+
+sub message { $X ? `gmessage -default Ok -buttons Ok "$_[0]"` : print SAVEOUT "$_[0]\n"; }
+sub member($@) { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 }
+sub uniq { my %l; @l{@_} = (); keys %l }
+sub difference2(\@\@) { my %l; @l{@{$_[1]}} = (); grep { !exists $l{$_} } @{$_[0]} }
+sub _ { my $s = shift @_; sprintf translate($s), @_ }
+sub translate { $I18N{$_[0]} || $_[0]; }
+
+sub untaint {
+ my @r = ();
+ foreach (@_) {
+ /(.*)/;
+ push @r, $1;
+ }
+ @r == 1 ? $r[0] : @r
+}
+
+sub load_po {
+ my ($from, $to, $state, $fuzzy);
+ local *F; open F, "/usr/share/locale/$_[0]/LC_MESSAGES/urpmi.po" or return;
+ foreach (<F>) {
+ /^msgstr/ and $state = 1;
+ /^msgid/ && !$fuzzy and $state = 2;
+
+ if (/^(#|$)/ && $state != 3) {
+ $state = 3;
+ s/\\n/\n/g foreach $from, $to;
+ $I18N{$from} = $to if $from;
+ $from = $to = '';
+ }
+ $to .= (/"(.*)"/)[0] if $state == 1;
+ $from .= (/"(.*)"/)[0] if $state == 2;
+
+ $fuzzy = /^#, fuzzy/;
+ }
+}
diff --git a/urpmi.8 b/urpmi.8
new file mode 100644
index 00000000..ca3e259d
--- /dev/null
+++ b/urpmi.8
@@ -0,0 +1,84 @@
+.TH urpmi 8 "18 Nov 1999" "Mandrakesoft" "Linux-Mandrake"
+.IX urpmi
+.SH NAME
+urpmi \- rpm wrapper making installs easier for the user
+.SH SYNOPSIS
+.B urpmi
+[--auto]
+package_name
+[package_names...]
+.SH DESCRIPTION
+urpmi enables non-superuser install of rpms. In fact, it only authorizes
+well-known rpms to be installed.
+
+You can compare rpm vs. urpmi with insmod vs. modprobe
+.PP
+All users belonging to group urpmi are allowed to install packages.
+.br
+Just launch urpmi followed by what you think is the name of the package(s), and urpmi will:
+.br
+\- Propose different package names if availables and quit.
+.br
+\- If found only one Package corresponding, check wether dependencies are already installed or not.
+.br
+\- If not, propose to install the dependencies and then install all required dependencies and the package.
+.PP
+Note that urpmi handle installations from various medias (ftp, local and nfs volumes, removable medias such as CDROMs) and is able to install dependencies from a media different from the package's media. If necessary, urpmi asks you to insert the required media.
+.PP
+To add a new media containing rpms run urpmi.addmedia.
+.br
+To remove a media use urpmi.removemedia.
+.br
+To update the packages list (for example when the ftp archive changed) use urpmi.update.
+.br
+To automatically install a package corresponding to an executable you tried to launch, use autoirpm.
+.br
+To install all available menu entries of all known packages, use autoirpm-icons.
+.SH OPTION
+.IP "\fB\--auto\fP"
+installs all required dependencies without asking.
+.SH FILES
+/usr/bin/urpmi
+.br
+The \fBurpmi\fP executable (perl script)
+.PP
+/etc/urpmi/list.*
+.br
+Contains the list of all packages known by urpmi and their location. There is one filelist per media(*).
+.PP
+/etc/urpmi/hdlist.*
+.br
+Contain information about all known packages, it's a summary of rpm headers. There is one filelist per media(*).
+.PP
+/etc/urpmi/urpmi.cfg
+.br
+Contains one line <\fIname\fP> <\fIurl\fP> per media.
+.PP
+/etc/urpmi/depslist
+.br
+A simple text file containning all dependencies of all known packages.
+.PP
+/etc/urpmi/depslist
+.br
+The same but in html format, user readable.
+.SH "SEE ALSO"
+urpmi.addmedia(8),
+urpmi.removemedia(8),
+urpmi.update(8),
+autoirpm(8),
+autoirpm-icons(8),
+gurpmi(8),
+rpmdrake(8)
+.SH AUTHOR
+Pascal Rigaux, Mandrakesoft
+.br
+pixel@mandrakesoft.com
+
+
+
+
+
+
+
+
+
diff --git a/urpmi.addmedia b/urpmi.addmedia
new file mode 100755
index 00000000..95f85adf
--- /dev/null
+++ b/urpmi.addmedia
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+my $DIR = "/etc/urpmi";
+my $DEPSLIST = "$DIR/depslist";
+my $CFG = "$DIR/urpmi.cfg";
+
+$| = 1;
+
+
+sub substInFile(&@) {
+ my $f = shift;
+ local @ARGV = @_ or return;
+ local ($^I, $_) = '';
+ while (<>) { &$f($_); print }
+}
+
+
+my @entries = map { /list.(.*)/ } glob("$DIR/list.*");
+
+if ($0 =~ /removemedia/) {
+ local ($_) = @ARGV or die "missing the entry to remove\n(one of " . join(", ", @entries) . ")\n";
+ foreach $e (/^--?a/ ? @entries : @ARGV) {
+ my $f;
+ $f = "$DIR/hdlist.$e"; unlink $f or die "failed to remove $f";
+ $f = "$DIR/list.$e"; unlink $f or die "failed to remove $f";
+ substInFile { s/^/\#/ if /^$e\s/ } $CFG;
+ }
+ system("urpmi.update");
+ exit 0;
+} elsif ($0 =~ /update/) {
+ if (local ($_) = @ARGV) {
+ my $regexp = /^--?a/ ? '[^#]\S*' : join('|', @ARGV);
+ system("urpmi.addmedia --noupdate $_") foreach grep { /^$regexp\s/ } `cat $CFG`;
+ }
+ if (glob("$DIR/hdlist.*")) {
+ print "generating dependencies list\n";
+ system("gendepslist -h $DEPSLIST $DIR/hdlist.*");
+ system("autoirpm.update");
+ } else {
+ unlink $DEPSLIST, "$DEPSLIST.html";
+ }
+ exit 0;
+}
+
+my $noupdate = shift @ARGV if $ARGV[0] eq "--noupdate";
+my ($name, $url, $with, $ftp_hdlist) = @ARGV;
+my $suffix;
+
+# basic checking of arguments
+{
+ my $usage =
+"usage: urpmi.addmedia <name> <url>
+where <url> is one of
+ file://<path>
+ ftp://<login>:<user>@<host>/<path> with <relative path of hdlist>
+ ftp://<host>/<path> with <relative path of hdlist>
+ http://<host>/<path> with <relative path of hdlist>
+ removable_<device>_<number>://<path>
+";
+ $name or die $usage;
+ my ($type, $dev, $num) = $url =~ m,^(file|ftp|http|removable_(\w+)_(\d+))://, or die $usage;
+ $name =~ s/\s/_/g;
+
+ if ($type eq "removable") {
+ $num =~ /^\d+$/ or die "$usage bad number (is `$num')\n";
+ $dev && -e "/dev/$dev" or die "$usage device `$dev' do not exist\n";
+ } elsif ($type eq "ftp") {
+ $with eq "with" or die "$usage `with' missing for ftp media\n";
+ $ftp_hdlist or die "$usage <relative path of hdlist> missing\n";
+ }
+}
+
+-e $CFG or `echo > $CFG`; # create it if not there
+$? == 0 or die "can't write to config file $CFG";
+substInFile {
+ s/^/\#/ if /^$name\s/;
+ $_ .= "$name $url $with $ftp_hdlist\n" if eof;
+} $CFG;
+
+
+my $HDLIST = "$DIR/hdlist.$name";
+my $RPMLIST = "$DIR/list.$name";
+
+-e $DIR || mkdir $DIR, 0755 or die "can't create $DIR";
+!-e $HDLIST || unlink $HDLIST or die "can't remove $HDLIST";
+
+my $mask = umask 077;
+open LIST, ">$RPMLIST" or die "can't output $RPMLIST";
+umask $mask;
+
+if (my ($prefix, $dir) = $url =~ m,^(removable_.*?|file):/(.*),) {
+ my $hdlist = '';
+ my $flush = sub {};
+ if (-e (my $f = "$dir/Mandrake/base/hdlist")) {
+ system("cp -f $f $HDLIST");
+ } else {
+ $flush = sub { system("rpm2header $hdlist >> $HDLIST") if $hdlist };
+ }
+ print "scanning $dir...";
+ open F, "find $dir -follow -name '*.rpm'|";
+ foreach (<F>) {
+ chomp;
+ if (length "$hdlist $_" > 1500) {
+ &$flush();
+ $hdlist = '';
+ }
+ $hdlist .= " $_";
+ print LIST "$prefix:/$_\n";
+ }
+ $hdlist or die "no rpms found in $dir";
+ &$flush();
+ close F or die "searching for rpms failed";
+ print "\n";
+} else {
+ system("wget -O $HDLIST $url/$ftp_hdlist");
+ $? == 0 or die "wget of $url/$ftp_hdlist failed (maybe wget is missing?)";
+ open F, "hdlist2files $HDLIST|";
+ foreach (<F>) {
+ chomp;
+ print LIST "$url/$_\n";
+ }
+ close F or die "hdlist2files failed";
+}
+close LIST;
+
+system("urpmi.update") unless $noupdate;
+exit 0;
diff --git a/urpmi.addmedia.8 b/urpmi.addmedia.8
new file mode 100644
index 00000000..dd9799ce
--- /dev/null
+++ b/urpmi.addmedia.8
@@ -0,0 +1,86 @@
+.TH urpmi.addmedia 8 "18 Nov 1999" "Mandrakesoft" "Linux-Mandrake"
+.IX urpmi.addmedia
+.SH NAME
+urpmi.addmedia \- adds a new rpms media for use with urpmi
+.SH SYNOPSIS
+.B urpmi.addmedia <\fIname\fP> <\fIurl\fP>
+.SH DESCRIPTION
+urpmi.addmedia tells urpmi that he can find new rpms at the specified location. Currently supported medias are: local drives, removable drives (such as cd's), http and ftp.
+.PP
+All users belonging to group urpmi are allowed to add a new media.
+.PP
+One of the following modes must be choosen:
+.PP
+http:
+.br
+.IP "\fB urpmi.addmedia <\fIname\fP> http://<\fIhost\fP>/<\fIpath\fP> with <\fIrelative path of hdlist\fP>\fP"
+Where <\fIname\fP> is your reference for the media (e.g. MandrakeUpdate).
+.br
+<\fIhost\fP>/<\fIpath\fP> is the location of the rpm directory on the net.
+.br
+<\fIrelative path of hdlist\fP> is the pathname where to find the hdlist of the rpms. The location is given relative to <\fIpath\fP>.
+.PP
+ftp:
+.br
+.IP "\fB urpmi.addmedia <\fIname\fP> ftp://<\fIlogin\fP>:<\fIuser\fP>@<\fIhost\fP>/<\fIpath\fP> with <\fIrelative path of hdlist\fP>\fP"
+The same as for http, just add your login and user if required (Note that you needn't to specify anonymous as login for anonymous access ftp servers).
+.PP
+Local drive or NFS:
+.br
+.IP "\fB urpmi.addmedia <\fIname\fP> file://<\fIpath\fP>\fP"
+Where <\fIname\fP> is your reference for the media (e.g. Myrpms).
+.br
+<\fIpath\fP> is the location of the rpm directory on your machine.
+.PP
+Removable device:
+.br
+.IP "\fB urpmi.addmedia removable_<\fIdevice\fP>_<\fInumber\fP>://<\fIpath\fP>\fP"
+<\fIdevice\fP> is the name of your media as specified in the /dev/ directory (e.g. cdrom, floppy, zip, ...).
+.br
+<\fInumber\fP> is used urpmi to choose in what order medias are inserted in case of multiple medias install with dependencies. '1' is reserved for the origin install medias.
+.PP
+
+.SH FILES
+/usr/bin/urpmi
+.br
+The \fBurpmi\fP executable (perl script)
+.PP
+/etc/urpmi/list.*
+.br
+Contains the list of all packages known by urpmi and their location. There is one filelist per media(*).
+.PP
+/etc/urpmi/hdlist.*
+.br
+Contain information about all known packages, it's a summary of rpm headers. There is one filelist per media(*).
+.PP
+/etc/urpmi/urpmi.cfg
+.br
+Contains one line <\fIname\fP> <\fIurl\fP> per media.
+.PP
+/etc/urpmi/depslist
+.br
+A simple text file containing all dependencies of all known packages.
+.PP
+/etc/urpmi/depslist.html
+.br
+The same but in html format, user readable.
+.SH "SEE ALSO"
+urpmi(8),
+urpmi.removemedia(8),
+autoirpm(8),
+autoirpm-icons(8),
+gurpmi(8),
+rpmdrake(8)
+.SH AUTHOR
+Pascal Rigaux, Mandrakesoft
+.br
+pixel@mandrakesoft.com
+
+
+
+
+
+
+
+
+
diff --git a/urpmi.removemedia.8 b/urpmi.removemedia.8
new file mode 100644
index 00000000..d4c84ca4
--- /dev/null
+++ b/urpmi.removemedia.8
@@ -0,0 +1,55 @@
+.TH urpmi.removemedia 8 "18 Nov 1999" "Mandrakesoft" "Linux-Mandrake"
+.IX urpmi.removemedia
+.SH NAME
+urpmi.removemedia \- remove a rpms media from the known medias of urpmi
+.SH SYNOPSIS
+.B urpmi.removemedia <\fIname\fP>
+.SH DESCRIPTION
+urpmi.removemedia removes from all configuration files all references to the named media and to rpms from that media.
+.PP
+<\fIname\fP> is the name you first told to urpmi.addmedia
+
+.SH FILES
+/usr/bin/urpmi
+.br
+The \fBurpmi\fP executable (perl script)
+.PP
+/etc/urpmi/list.*
+.br
+Contains the list of all packages known by urpmi and their location. There is one filelist per media(*).
+.PP
+/etc/urpmi/hdlist.*
+.br
+Contain information about all known packages, it's a summary of rpm headers. There is one filelist per media(*).
+.PP
+/etc/urpmi/urpmi.cfg
+.br
+Contains one line <\fIname\fP> <\fIurl\fP> per media.
+.PP
+/etc/urpmi/depslist
+.br
+A simple text file containing all dependencies of all known packages.
+.PP
+/etc/urpmi/depslist.html
+.br
+The same but in html format, user readable.
+.SH "SEE ALSO"
+urpmi(8),
+urpmi.addmedia(8),
+autoirpm(8),
+autoirpm-icons(8),
+gurpmi(8),
+rpmdrake(8)
+.SH AUTHOR
+Pascal Rigaux, Mandrakesoft
+.br
+pixel@mandrakesoft.com
+
+
+
+
+
+
+
+
+