Files
alien/alien
2000-04-21 22:48:23 +00:00

421 lines
11 KiB
Perl
Executable File

#!/usr/bin/perl
=head1 NAME
alien - Convert or install an alien binary package
=head1 SYNOPSIS
alien [--to-deb] [--to-rpm] [--to-tgz] [--to-slp] [options] file [...]
=head1 DESCRIPTION
B<alien> is a program that converts between Redhat rpm, Debian deb,
Stampede slp and Slackware tgz file formats. If you want to use a package from
another linux distribution than the one you have installed on your system,
you can use alien to convert it to your preferred package format and install it.
=head1 WARNING
Despite the high version number, alien is still (and will probably always
be) rather experimental software. It's been under development for many
years now, but there are still many bugs and limitations.
Alien should not be used to replace important system packages, like
init, libc, or other things that are essential for the functioning of
your system. Many of these packages are set up differently by the
different distributions, and packages from the different distributions
cannot be used interchangeably. In general, if you can't remove a
package without breaking your system, don't try to replace it with an
alien version.
=head1 PACKAGE FORMAT NOTES
=over 4
=item rpm
For converting to and from rpm format the Red Hat Package Manager must be
installed.
=item deb
For converting to (but not from) deb format, the gcc, make, debmake,
dpkg-dev, and dpkg packages must be installed.
=item tgz
Note that when converting from the tgz format, B<alien> will simply generate an
output package that has the same files in it as are in the tar file. This
only works well if the tar file has precompiled binaries in it in a
standard linux directory tree. Do NOT run alien on tar files with source
code in them, unless you want this source code to be installed in your root
directory when you install the package!
=back
=head1 OPTIONS
Alien will convert all the files you pass into it into all the output types
you specify. If no output type is specified, it defaults to converting to
deb format.
=over 4
=item file [...]
The list of package files to convert.
=item B<-d>, B<--to-deb>
Make debian packages. This is the default.
=item B<-r>, B<--to-rpm>
Make rpm packages.
=item B<-t>, B<--to-tgz>
Make tgz packages.
=item B<--to-slp>
Make slp packages.
=item B<-i>, B<--install>
Automatically install each generated package, and remove the package file
after it has been installed.
=item B<-g>, B<--generate>
Generate a temporary directory suitable for building a package from, but do
not actually create the package. This is useful if you want to move files
around in the package before building it. The package can be built from
this temporary directory by running "debian/rules binary", if you were creating
a Debian package, or by running "rpm -bb <packagename>.spec" if you were
creating a Red Hat package.
=item B<-s>, B<--single>
Like -g, but do not generate the packagename.orig directory. This is only
useful when you are very low on disk space and are generating a debian
package.
=item B<--patch=>I<patch>
Specify the patch to be used instead of automatically looking the patch up
in B</var/lib/alien>. This has no effect unless a debian package is being
built.
=item B<--nopatch>
Do not use any patch files.
=item B<--description=>I<desc>
Specifiy a description for the package. This only has an effect when
converting from the tgz package format, which lacks descriptions.
=item B<-c>, B<--scripts>
Try to convert the scripts that are meant to be run when the
package is installed and removed. Use this with caution, becuase these
scripts might be designed to work on a system unlike your own, and could
cause problems. It is recommended that you examine the scripts by hand
and check to see what they do before using this option.
=item B<-k>, B<--keep-version>
By default, alien adds one to the minor version number of each package it
converts. If this option is given, alien will not do this.
=item B<-h>, B<--help>
Display a short usage summary.
=back
=head1 EXAMPLES
Here are some examples of the use of alien:
=over 4
=item alien --to-deb package.rpm
Convert the package.rpm into a package.deb
=item alien --to-rpm package.deb
Convert the package.deb into a package.rpm
=item alien -i package.rpm
Convert the package.rpm into a package.deb (converting to a .deb package is
default, so you need not specify --to-deb), and install the generated
package.
=item alien --to-deb --to-rpm --to-tgz --to-slp foo.deb bar.rpm baz.tgz
Creates 9 new packages. When it is done, foo bar and baz are available in
all 4 package formats.
=back
=head1 ENVIRONMENT
Alien recognizes the following environemnt variables:
=over 4
=item RPMBUILDOPT
Options to pass to rpm when it is building a package.
=item RPMINSTALLOPT
Options to pass to rpm when it is installing a package.
=back
=head1 NOTES
When using alien to convert a tgz package, all files in /etc in are assumed to be
configuration files.
If alien is not run as root, the files in the generated package will have
incorrect owners and permissions.
=head1 AUTHOR
Alien was written by Christoph Lameter, B<<clameter@debian.org>>.
Deb to rpm conversion code was taken from the Martian program by
Randolph Chung, B<<rc42@cornell.edu>>.
Alien has been extensively rewritten (3 times) and is now maintained by Joey Hess
B<<joeyh@debian.org>>.
=head1 COPYRIGHT
Alien may be copied amd modified under the terms of the GNU General Public
License.
=cut
use strict;
# Globals.
use vars qw($desttype $file $filetype $generate $install $workdir $libdir
$keep_version $scripts $tgzdescription $patchfile $nopatch $single
$prefix @patchdirs);
BEGIN {
$prefix="/usr"; # PREFIX_AUTOREPLACE done by Makefile, do not edit.
# Directory where alien templates, etc, are stored.
$libdir="$prefix/share/alien";
push @INC, $libdir;
}
# Directories where alien patches are stored.
@patchdirs=('/var/lib/alien',"$prefix/lib/alien/patches");
use Getopt::Long;
# Load up all of alien's modules.
use Alien;
use Fromrpm;
use Fromdeb;
use Fromtgz;
use Fromslp;
use Torpm;
use Todeb;
use Totgz;
use Toslp;
# Display alien's version number.
sub Version {
my $version_string='unknown'; # VERSION_AUTOREPLACE done by Makefile, do not edit.
print "Alien version $version_string\n";
}
# Display usage help.
sub Usage {
print <<eof;
Usage: alien [options ...] file [...]
file [...] Package file or files to convert.
-d, --to-deb Generate a Debian deb package. (default)
Enables the following options:
--patch=<patch> Specify patch file to use instead of automatically
looking for patch in /var/lib/alien.
--nopatch Do not use patches.
-r, --to-rpm Generate a RedHat rpm package.
-t, --to-tgz Generate a Slackware tgz package.
--to-slp Generate a Stampede .slp package.
-i, --install Install generated package.
-g, --generate Unpack, but do not generate a new package.
-s, --single Like --generate, but do not create .orig directory.
-c, --scripts Include scripts in package.
-k, --keep-version Do not change version of generated package.
--description=<desc> Specify package description.
-h, --help Display this help message.
-v, --version Display alien's version number.
eof
}
# Process parameters.
# Sets some global variables.
sub GetParams {
my ($todeb, $torpm, $totgz, $toslp, $help, $version);
# Get options.
my $ret=GetOptions(
"to-deb|d", \$todeb,
"to-rpm|r", \$torpm,
"to-tgz|t", \$totgz,
"to-slp", \$toslp,
"generate|g", \$generate,
"install|i", \$install,
"single|s", \$single,
"scripts|c", \$scripts,
"patch|p=s", \$patchfile,
"nopatch", \$nopatch,
"description=s", \$tgzdescription,
"keep-version|k", \$keep_version,
"help|h", \$help,
"version|v", \$version,
);
if (!$ret) {
Usage();
exit 1;
}
if ($version) {
Version();
exit 1;
}
if ($help) {
Usage();
exit;
}
if ($single) {
$generate=1;
}
if ($todeb) {
$desttype='deb'
}
elsif ($torpm) {
$desttype='rpm';
}
elsif ($totgz) {
$desttype='tgz';
}
elsif ($toslp) {
$desttype='slp';
}
else {
$desttype='deb';
}
# Sanity check options.
if ($desttype ne 'deb' && $patchfile) {
Usage();
Alien::Error("You can not use --patch with --to-rpm or --to-tgz or --to-slp");
}
if (($generate || $single) && $install) {
Usage();
Alien::Error("You can not use --generate or --single with --install");
}
if ($patchfile && ! -f $patchfile) {
Alien::Error("Specified patch file, \"$patchfile\" was not be found.");
}
if ($patchfile && $nopatch) {
Alien::Error("The options --nopatch and --patchfile cannot be used together.");
}
if (!@ARGV) {
Usage();
Alien::Error("You must specify a file to convert.");
}
}
# Check alien's working anvironment.
sub TestEnviron() {
if (! -w '.') {
Alien::Error("Cannot write to current directory. Try changing to /tmp and re-running alien.");
}
if ($> ne 0) {
if ($desttype eq 'deb' && ! $generate && ! $single) {
Alien::Error("Must run as root to convert to .deb format (or you may use fakeroot).");
}
Alien::Warning("Warning: alien is not running as root!");
Alien::Warning("Ownerships of files in the generated packages will");
Alien::Warning("probably be messed up.");
}
}
# Main program:
# Initialization and data collection.
GetParams();
TestEnviron();
foreach $file (@ARGV) {
if (! -f $file) {
Alien::Error("File $file not found.\n");
}
$filetype=Alien::FileType($file);
if ($filetype eq $desttype) {
Alien::Error("There is no point in converting a $filetype into a $desttype.");
}
Alien::Status("Examining $file");
# These variables are set to let us refer to the proper packages
# to process the source and destination file types.
my $dest="To::$desttype";
my $src="From::$filetype";
my %fields=$dest->FixFields($src->GetFields($file));
# Unpack stage.
Alien::Status("Unpacking $file");
$workdir="$fields{NAME}-$fields{VERSION}";
Alien::SafeMkdir($workdir);
chdir $workdir;
$src->Unpack($file,%fields);
chdir "..";
# Conversion stage.
$dest->Convert($workdir,$nopatch,%fields);
# Build stage.
if (!$generate) {
my $packagename=$dest->GetPackageName(%fields);
Alien::Status("Building the package $packagename");
chdir $workdir;
$dest->Build(%fields);
chdir "..";
Alien::SafeSystem("rm -rf $workdir");
# The above "building $packagename..." message can get lost in the
# noise, so tell them again where the package ended up.
print "\nGeneration of $packagename complete.\n" if !$install;
}
# Install stage.
if ($install) {
my $packagename=$dest->GetPackageName(%fields);
Alien::Status("Installing generated $desttype package");
$dest->Install($packagename);
unlink $packagename;
}
}
Alien::Status("Successfully finished");