diff options
| author | fukachan <fukachan> | 2003-01-28 04:16:16 +0000 |
|---|---|---|
| committer | fukachan <fukachan> | 2003-01-28 04:16:16 +0000 |
| commit | ad9332ceadc2fb94cb1515efd0ca0332a188eb95 (patch) | |
| tree | f063b8ba0fc7070b2857016688387672a9c8a711 | |
| parent | 32df1cf02b3796d632dd5db19800b7629e1c8d20 (diff) | |
| download | fml8-ad9332ceadc2fb94cb1515efd0ca0332a188eb95.tar.gz fml8-ad9332ceadc2fb94cb1515efd0ca0332a188eb95.tar.bz2 fml8-ad9332ceadc2fb94cb1515efd0ca0332a188eb95.zip | |
installer perl version
| -rw-r--r-- | fml/etc/install.cf.in | 104 | ||||
| -rw-r--r-- | fml/lib/FML/Install.pm | 974 | ||||
| -rwxr-xr-x | install.pl.in | 85 |
3 files changed, 1163 insertions, 0 deletions
diff --git a/fml/etc/install.cf.in b/fml/etc/install.cf.in new file mode 100644 index 00000000..f43990a0 --- /dev/null +++ b/fml/etc/install.cf.in @@ -0,0 +1,104 @@ +# +# Copyright (C) 2003 Ken'ichi Fukamachi +# All rights reserved. This program is free software; you can +# redistribute it and/or modify it under the same terms as Perl itself. +# +# $FML$ +# + + +LIBS = @LIBS@ + +CC = @CC@ + +CFLAGS = @CFLAGS@ + +LDFLAGS = @LDFLAGS@ + +INSTALLCMD = @INSTALL@ + + +prefix = @prefix@ + +exec_prefix = @exec_prefix@ + +bindir = @bindir@ + +mandir = @mandir@ + +config_dir = @fmlconfdir@ + +libexec_dir = @libexecdir@/fml + +lib_dir = @libdir@/fml + +data_dir = @datadir@/fml + + +# ml spool +ml_spool_dir = @mlspooldir@ + + +# owner of /var/spool/ml +owner = @fml_owner@ + +group = @fml_group@ + + + +vendors = fml + cpan + img + +mandatory_dirs = prefix + exec_prefix + config_dir + default_config_dir + bindir + mandir + libexec_dir + lib_dir + data_dir + +# install /etc/fml/defauls/$version/ +nl_template_files = default_config.cf + config.cf + + +# install /etc/fml/defauls/$version/ +template_files = include + include-ctl + include-error + aliases + postfix_virtual + dot_htaccess + dot-qmail + dot-qmail-admin + dot-qmail-ctl + dot-qmail-default + dot-qmail-request + procmailrc + + +bin_programs = fml + fmladdr + fmlalias + fmldoc + fmlthread + fmlconf + fmlerror + makefml + fmlsch + fmlhtmlify + fmlspool + fmlsummary + fmlsuper + + +libexec_programs = fml.pl + distribute + digest + command + error + mead + fmlserv diff --git a/fml/lib/FML/Install.pm b/fml/lib/FML/Install.pm new file mode 100644 index 00000000..91b49958 --- /dev/null +++ b/fml/lib/FML/Install.pm @@ -0,0 +1,974 @@ +#-*- perl -*- +# +# Copyright (C) 2003 Ken'ichi Fukamachi +# All rights reserved. This program is free software; you can +# redistribute it and/or modify it under the same terms as Perl itself. +# +# $FML$ +# + +package FML::Install; + +use strict; +use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD $debug); +use Carp; +use FileHandle; +use File::Spec; +use File::Copy; +use File::Basename; + + +=head1 NAME + +FML::Install - utility functions used in installation + +=head1 SYNOPSIS + + # use FML::Install; + my $installer = new FML::Install; + my $config = $installer->load_install_cf( $cf ); + + printf $format, "version", $installer->get_version() if $debug; + + my $list = $config->get_as_array_ref('mandatory_dirs'); + for my $dir (@$list) { + my $path = $installer->path($dir); + printf $format, $dir, $path if $debug; + unless (-d $path) { + $installer->mkdir($path); + } + else { + print STDERR "ok $path\n" if $debug; + } + } + + # XXX-TODO: check uid, gid + + $installer->install_main_cf(); + $installer->install_sample_cf_files(); + $installer->install_default_config_files(); + $installer->install_mtree_dir(); + $installer->install_lib_dir(); + $installer->install_libexec_dir(); + $installer->install_data_dir(); + + # install programs hereafter. + $installer->install_bin_programs(); + + # update loader. + if ( $installer->need_resymlink_loader() ) { + $installer->install_loader(); + $installer->resymlink_loader(); + } + + # set up ml_spool_dir such as /var/spool/ml if needed. + $installer->setup_ml_spool_dir(); + +=head1 DESCRIPTION + +Our installer C<install.pl> at the fml8 top directory uses this +module. + +=head1 METHODS + +=head2 C<new()> + +constructor. + +=cut + + +# Descriptions: constructor. +# Arguments: OBJ($self) +# Side Effects: initiailze $self->{ _show_message } flag. +# Return Value: OBJ +sub new +{ + my ($self) = @_; + my ($type) = ref($self) || $self; + my $me = {}; + + # show several messages by default + enable_message($me); + + return bless $me, $type; +} + + +=head1 CONFIG + +=head2 load_install_cf( $cf ) + +read the specified config file, initialize and return config object. + +=cut + + +# Descriptions: read the specified config file and initialize config object +# Arguments: OBJ($self) STR($cf) +# Side Effects: initialize configuration object +# Return Value: OBJ +sub load_install_cf +{ + my ($self, $cf) = @_; + + use FML::Config; + my $config = new FML::Config; + croak( $config->error() ) if $config->error(); + + if (-f $cf) { + $config->load_file( $cf ); + croak( $config->error() ) if $config->error(); + + $config->update(); + $self->{ _config } = $config; + return $config; + } + else { + croak("no such file: $cf"); + } + + return undef; +} + + +=head1 INSTALL METHODS + +=head2 convert($src, $dst, [$mode]) + +create $dst with variable substitutions. +In addition, chmod() if $mode specified. + +=cut + + +# Descriptions: create $dst with variable substitutions. +# Arguments: OBJ($self) STR($src) STR($dst) +# Side Effects: create $dst file. +# Return Value: none +sub convert +{ + my ($self, $src, $dst, $mode) = @_; + my $tmp = $dst. ".new.$$"; + my $in = new FileHandle $src; + my $out = new FileHandle "> $tmp"; + + # special flag to influence message + my $dst_already_exist = -f $out ? 1 : 0; + my $is_show_message = $self->_is_show_message(); + + if (defined $in && defined $out) { + my $version = $self->get_version(); + + my $buf = ''; + while ($buf = <$in>) { + $buf =~ s/__fml_version__/$version/; + print $out $buf; + } + + $out->close(); + $in->close(); + + if (rename($tmp, $dst)) { + if (-f $dst) { + if (defined $mode) { chmod $mode, $dst;} + + if ($is_show_message) { + if ($dst_already_exist) { + print STDERR "updating $dst\n"; + } + else { + print STDERR "creating $dst\n"; + } + } + } + else { + _errmsg("fail to create $dst"); + } + } + else { + _errmsg("fail to rename $tmp $dst"); + } + } + else { + _errmsg("cannot open $src") unless defined $in; + _errmsg("cannot open $dst") unless defined $out; + _errmsg("fail to create $dst"); + } +} + + +=head2 install_main_cf() + +install main.cf e.g. /etc/fml/main.cf. + +=cut + + +# Descriptions: install main.cf +# Arguments: OBJ($self) +# Side Effects: create main.cf. +# Return Value: none +sub install_main_cf +{ + my ($self) = @_; + + # XXX src = relative path, dst = absolute path + my $src = File::Spec->catfile("fml", "etc", "main.cf"); + my $config_dir = $self->path( 'config_dir' ); + my $dst = File::Spec->catfile($config_dir, "main.cf"); + + if (-f $dst) { + print STDERR "skipping $dst (debug)\n" if $debug; + } + else { + $self->convert($src, $dst, 0644); + } +} + + +=head2 install_sample_cf_files() + +install sample .cf files: + + site_default_config.cf + mime_component_filter + +=cut + + +# Descriptions: install sample .cf files. +# Arguments: OBJ($self) +# Side Effects: create sample .cf files in /etc/fml/. +# Return Value: none +sub install_sample_cf_files +{ + my ($self) = @_; + my $config_dir = $self->path( 'config_dir' ); + + for my $file (qw(site_default_config.cf + mime_component_filter)) { + # XXX src = relative path, dst = absolute path + my $src = File::Spec->catfile("fml", "etc", $file); + my $dst = File::Spec->catfile($config_dir, $file); + + if (-f $dst) { + print STDERR "skipping $dst (debug)\n" if $debug; + } + else { + $self->convert($src, $dst, 0644); + } + } +} + + +=head2 install_default_config_files() + +install default templates at /etc/fml/defautls/$version/. + +=head2 install_mtree_dir() + +install mtree info at /etc/fml/defautls/$version/mtree/. + +=cut + + +# Descriptions: install default templates. +# Arguments: OBJ($self) +# Side Effects: create files in /etc/fml/defaults/$version/. +# Return Value: none +sub install_default_config_files +{ + my ($self) = @_; + my $config = $self->{ _config }; + my $config_dir = $self->path( 'default_config_dir' ); + + print STDERR "updating $config_dir\n"; + + $self->disable_message(); + + my $nl_template_files = $config->get_as_array_ref('nl_template_files'); + for my $file (@$nl_template_files) { + # XXX-TODO: how should we handle natural language .cf ? + # XXX src = relative path, dst = absolute path + my $src = File::Spec->catfile("fml", "etc", $file . ".ja"); + my $dst = File::Spec->catfile($config_dir, $file); + + # always override. + $self->convert($src, $dst, 0644); + } + + my $template_files = $config->get_as_array_ref('template_files'); + for my $file (@$template_files) { + # XXX src = relative path, dst = absolute path + my $src = File::Spec->catfile("fml", "etc", $file); + my $dst = File::Spec->catfile($config_dir, $file); + + # always override. + $self->convert($src, $dst, 0644); + } + + $self->enable_message(); +} + + +# Descriptions: install mtree config. +# Arguments: OBJ($self) +# Side Effects: create files in /etc/fml/defaults/$version/mtree/. +# Return Value: none +sub install_mtree_dir +{ + my ($self) = @_; + my $config = $self->{ _config }; + + # XXX src = relative path, dst = absolute path + my $dst_dir = File::Spec->catfile($self->path( 'default_config_dir' ), + "mtree"); + my $src_dir = File::Spec->catfile("fml", "etc", "mtree"); + + print STDERR "updating $dst_dir\n" if $debug; + $self->copy_dir( $src_dir, $dst_dir ); +} + + +=head2 install_lib_dir() + +install library (perl modules). + +=head2 install_libexec_dir() + +install libexec executables. + +=head2 install_data_dir() + +install files under fml/share/. + +=cut + + +# Descriptions: install perl modules. +# Arguments: OBJ($self) +# Side Effects: install lib/ +# Return Value: none +sub install_lib_dir +{ + my ($self) = @_; + my $config = $self->{ _config }; + my $dst_dir = $self->path( 'lib_dir' ); + my $src_dir = ''; + + print STDERR "updating $dst_dir\n"; + + my $vendors = $config->get_as_array_ref('vendors'); + for my $vendor (@$vendors) { + # XXX src = relative path, dst = absolute path + $src_dir = File::Spec->catfile($vendor, "lib"); + print STDERR " copying from $src_dir\n"; + $self->copy_dir( $src_dir, $dst_dir ); + } +} + + +# Descriptions: install executables. +# Arguments: OBJ($self) +# Side Effects: update libexec/. +# Return Value: none +sub install_libexec_dir +{ + my ($self) = @_; + + # XXX src = relative path, dst = absolute path + my $src_dir = File::Spec->catfile("fml", "libexec"); + my $dst_dir = $self->path( 'libexec_dir' ); + + print STDERR "updating $dst_dir\n"; + $self->copy_dir( $src_dir, $dst_dir ); +} + + +# Descriptions: install message files et.al. +# Arguments: OBJ($self) +# Side Effects: update share/. +# Return Value: none +sub install_data_dir +{ + my ($self) = @_; + + # XXX src = relative path, dst = absolute path + my $src_dir = File::Spec->catfile("fml", "share"); + my $dst_dir = $self->path( 'data_dir' ); + + print STDERR "updating $dst_dir\n"; + $self->copy_dir( $src_dir, $dst_dir ); +} + + +=head2 install_bin_programs() + +install utitily programs typically located at /usr/local/bin. + +=cut + + +# Descriptions: install utitily programs typically located at /usr/local/bin. +# Arguments: OBJ($self) +# Side Effects: update /usr/lcoal/bin/. +# Return Value: none +sub install_bin_programs +{ + my ($self) = @_; + my $config = $self->{ _config }; + my $progs = $config->get_as_array_ref('bin_programs'); + my $dst_dir = $self->path( 'bindir' ); + + for my $prog (@$progs) { + # XXX src = relative path, dst = absolute path + my $src = File::Spec->catfile("fml", "bin", $prog); + my $dst = File::Spec->catfile($dst_dir, $prog); + + print STDERR "updating $dst\n" if $debug; + unless (-f $dst) { + $self->_need_resymlink_loader(); + } + + # override always + $self->convert($src, $dst, 0755); + } +} + + +=head1 LOADER + +=head2 need_resymlink_loader() + +check if we need to update loader symlink? + +=head2 install_loader() + +install loader. + +=head2 resymlink_loader() + +re-symlink loader. + +=cut + + +# Descriptions: toggle on that we need to re-symlink loader. +# Arguments: OBJ($self) +# Side Effects: update $self->{ _need_resymlink_loader }. +# Return Value: 1 +sub _need_resymlink_loader +{ + my ($self) = @_; + $self->{ _need_resymlink_loader } = 1; +} + + +# Descriptions: check if we need to update loader symlink? +# Arguments: OBJ($self) +# Side Effects: none +# Return Value: NUM(1 or 0) +sub _is_need_resymlink_loader +{ + my ($self) = @_; + return( $self->{ _need_resymlink_loader } ? 1 : 0); +} + + +# Descriptions: check if we need to update loader symlink? +# Arguments: OBJ($self) +# Side Effects: none +# Return Value: NUM(1 or 0) +sub need_resymlink_loader +{ + my ($self) = @_; + my $status = 0; + my $config = $self->{ _config }; + + # XXX src = relative path, dst = absolute path + my $loader = File::Spec->catfile("fml", "libexec", "loader"); + my $libexec_dir = $config->{ libexec_dir }; + my $cur_loader = File::Spec->catfile($libexec_dir, "loader"); + + if ($debug) { + print STDERR "cur $cur_loader\n"; + print STDERR "new $loader\n"; + } + + # when new bin/$program found + return 1 if $self->_is_need_resymlink_loader(); + + my $cur_sum = $self->md5( $cur_loader ); + my $new_sum = $self->md5( $loader ); + + # need to update loader. + if ($cur_sum ne $new_sum) { + use Term::ReadLine; + my $term = new Term::ReadLine 'Simple Perl calc'; + my $prompt = "You must upgrade loader. Replace it ? [y/n]: "; + my $OUT = $term->OUT || \*STDOUT; + my $res = ''; + + READLINE: + while (defined ($res = $term->readline($prompt))) { + if ($res eq 'y' || $res eq 'Y') { + $status = 1; + last READLINE; + } + warn $@ if $@; + } + } + + return $status; +} + + +# Descriptions: install loader (fml/libexec/loader). +# Arguments: OBJ($self) +# Side Effects: update loader. +# Return Value: none +sub install_loader +{ + my ($self) = @_; + my $config = $self->{ _config }; + + # XXX src = relative path, dst = absolute path + my $loader = File::Spec->catfile("fml", "libexec", "loader"); + my $libexec_dir = $config->{ libexec_dir }; + my $cur_loader = File::Spec->catfile($libexec_dir, "loader"); + my $tmp = $cur_loader . ".$$"; + + use File::Copy; + copy($loader, $tmp); + chmod 0755, $tmp; + + unless (rename($tmp, $cur_loader)) { + _errmsg("fail to rename $tmp $cur_loader"); + } + + unless (-f $cur_loader) { + _errmsg("fail to install $cur_loader"); + croak("fail to install $cur_loader\n"); + } +} + + +# Descriptions: re-symlink executable to loader. +# Arguments: OBJ($self) +# Side Effects: update symlink. +# Return Value: none +sub resymlink_loader +{ + my ($self) = @_; + my $config = $self->{ _config }; + my $libexec_dir = $config->{ libexec_dir }; + my $cur_loader = File::Spec->catfile($libexec_dir, "loader"); + my $bin_programs = $config->get_as_array_ref('bin_programs'); + my $exec_programs = $config->get_as_array_ref('libexec_programs'); + + chdir $libexec_dir || croak("fail to chdir $libexec_dir"); + + print STDERR "symlink: loader to"; + my $p = length("symlink: loader to"); + my $n = $p; + for my $prog (@$bin_programs, @$exec_programs) { + $n += length(" $prog"); + print STDERR " $prog"; + + unlink($prog); + symlink("loader", $prog); + + if ($n > 72) { + print STDERR "\n"; + print STDERR " " x $p; + $n = $p; + } + } + print STDERR "\n"; +} + + +=head1 SET UP ML SPOOL + +=head2 setup_ml_spool_dir() + +set up $ml_spool_dir e.g. /var/spool/ml. + +=cut + + +# Descriptions: set up $ml_spool_dir. +# Arguments: OBJ($self) +# Side Effects: mkdir and chown /var/spool/ml. +# Return Value: none +sub setup_ml_spool_dir +{ + my ($self) = @_; + my $config = $self->{ _config }; + my $dir = $self->path( 'ml_spool_dir' ); + my $owner = $config->{ owner }; + my $group = $config->{ group }; + + if (-d $dir and -w $dir) { + print STDERR " * info: $dir exists. not touch it.\n"; + } + else { + print STDERR "creating $dir\n"; + $self->mkdir( $dir ); + + print STDERR " chown $owner:$group $dir\n"; + $self->chown( $owner, $group, $dir ); + } +} + + +=head1 UTILITY FUNCTIONS + +=head2 get_version() + +return fml version. +return current-YYYYMMDD if ".version" file is not found. + +=cut + + +# Descriptions: return fml version. +# Arguments: OBJ($self) +# Side Effects: none +# Return Value: STR +sub get_version +{ + my ($self) = @_; + my $vers = ''; + + if (-f ".version") { + use FileHandle; + my $fh = new FileHandle ".version"; + if (defined $fh) { + chomp($vers = <$fh>); + $fh->close; + } + } + + unless ($vers) { + use POSIX; + $vers = strftime("current-%C%y%m%d", localtime()); + } + + return $vers; +} + + +=head2 is_valid_owner( $owner ) + +check if $owner is a valid user ? + +=head2 is_valid_group( $group ) + +check if $group is a valid group ? + +=cut + + +# Descriptions: check if the $user is valid? +# Arguments: OBJ($self) STR($user) +# Side Effects: croak() if critical error found. +# Return Value: NUM(1 or 0) +sub is_valid_owner +{ + my ($self, $user) = @_; + + use User::pwent; + my $pw = getpwnam($user) || croak("no such user: $user"); + if ($pw->uid == 0) { + croak("user should be not ROOT!"); + } + + return 1; +} + + +# Descriptions: check if the $group is valid? +# Arguments: OBJ($self) STR($group) +# Side Effects: croak() if critical error found. +# Return Value: NUM(1 or 0) +sub is_valid_group +{ + my ($self, $group) = @_; + + use User::grent; + my $gr = getgrnam($group) || croak("no such group: $group"); + + return 1; +} + + +=head2 path( $dir ) + +return the absolute directory path for the specified type C<$dir>. + +=cut + + +# Descriptions: return the absolute dir path for the type $dir. +# Arguments: OBJ($self) STR($dir) +# Side Effects: none +# Return Value: STR +sub path +{ + my ($self, $dir) = @_; + my $config = $self->{ _config }; + my $version = $self->get_version(); + my $config_dir = $config->{ config_dir }; + + if ($dir eq 'prefix' || + $dir eq 'exec_prefix' || + $dir eq 'config_dir' || + $dir eq 'bindir' || + $dir eq 'mandir' || + $dir eq 'ml_spool_dir') { + return $config->{ $dir }; + } + elsif ($dir eq 'default_config_dir') { + return File::Spec->catfile($config->{ config_dir }, + "defaults", + $version); + } + else { + if (defined $config->{ $dir }) { + return File::Spec->catfile($config->{ $dir }, $version); + } + else { + return ''; + } + } +} + + +=head1 UTILITY FUNCTIONS FOR FILE HANDLING + +=head2 mkdir( $dir, [$mode] ) + +mkdir $dir with the mode $mode if $mode specified. +Whereas, mkdir $dir with the mode 0755 if $mode unspecified. + +=head2 copy_dir( $src_dir, $dst_dir ) + +copy files recursively. + +=head2 chown( $owner, $group, $dir ) + +chown $owner:$group $dir. + +=cut + + +# Descriptions: mkdir $dir with the mode $mode +# Arguments: OBJ($self) STR($dir) NUM($mode) +# Side Effects: mkdir $dir +# Return Value: none +sub mkdir +{ + my ($self, $dir, $mode) = @_; + + unless (-d $dir) { + use File::Path; + mkpath( [ $dir ], 0, ($mode || 0755) ); + } +} + + +my @_cache = (); + + +# Descriptions: copy all files recursively. +# Arguments: OBJ($self) STR($src_dir) STR(dst_dir) +# Side Effects: update $dst_dir +# Return Value: none +sub copy_dir +{ + my ($self, $src_dir, $dst_dir) = @_; + + @_cache = (); # XXX global in this package. + + use File::Find; + find(\&_want_file, $src_dir); + + my $n; + for my $file (@_cache) { + $n = $file; + $n =~ s@$src_dir@@; + + my $src = $file; + my $dst = File::Spec->catfile( $dst_dir, $n ); + + my $dst_dir = dirname($dst); + unless (-d $dst_dir) { + print STDERR " ** ? ** $dst_dir\n" if -f $dst_dir; + $self->mkdir( $dst_dir ); + } + + if (-f $src && -f $dst) { + copy($src, $dst); + } + else { + print "warning $src -> $dst\n" if $debug; + } + } +} + + +# Descriptions: subroutine used by File::Find(). +# Arguments: none +# Side Effects: update @_cache +# Return Value: none +sub _want_file +{ + my ($s) = $File::Find::name; + + if ($s !~ /CVS/) { + push(@_cache, $s); + } +} + + +# Descriptions: chown +# Arguments: OBJ($self) STR($owner) STR($group) STR($dir) +# Side Effects: change owner and group of $dir +# Return Value: none +sub chown +{ + my ($self, $owner, $group, $dir ) = @_; + + use User::pwent; + my $pw = getpwnam($owner) || croak("no such user: $owner"); + my $uid = $pw->uid; + + use User::grent; + my $gr = getgrnam($group) || croak("no such group: $group"); + my $gid = $gr->gid; + + @_cache = (); # XXX global in this package. + + use File::Find; + find(\&_want_file, $dir); + + for my $file (@_cache) { + print STDERR "chown $uid, $gid, $file\n" if $debug; + chown $uid, $gid, $file; + } +} + + +=head2 md5( $file ) + +return MD5 checksum for the file. + +=cut + + +# Descriptions: return MD5 checksum for the file. +# Arguments: OBJ($self) STR($file) +# Side Effects: none +# Return Value: STR +sub md5 +{ + my ($self, $file) = @_; + my $buf = ''; + + my $fh = new FileHandle $file; + if (defined $fh) { + while (<$fh>) { $buf .= $_;} + $fh->close(); + } + + use Mail::Message::Checksum; + my $cksum = new Mail::Message::Checksum; + my $sum = $cksum->md5( \$buf ); + + return $sum; +} + + +=head1 MESSAGE MANIPULATION + +=head2 enable_message() + +enable verbose message output. + +=head2 disable_message() + +disable verbose message output. + +=cut + + +# Descriptions: enable message output. +# Arguments: OBJ($self) +# Side Effects: update $self->{ _show_message }. +# Return Value: NUM +sub enable_message +{ + my ($self) = @_; + $self->{ _show_message } = 1; +} + + +# Descriptions: disable message output. +# Arguments: OBJ($self) +# Side Effects: update $self->{ _show_message }. +# Return Value: NUM +sub disable_message +{ + my ($self) = @_; + $self->{ _show_message } = 0; +} + + +# Descriptions: check if we show message +# Arguments: OBJ($self) +# Side Effects: none +# Return Value: NUM +sub _is_show_message +{ + my ($self) = @_; + return $self->{ _show_message }; +} + + +# Descriptions: show error message by some predefined fomrat. +# Arguments: STR($s) +# Side Effects: none +# Return Value: none +sub _errmsg +{ + my ($s) = @_; + print STDERR " * error: $s\n"; +} + + +=head1 CODING STYLE + +See C<http://www.fml.org/software/FNF/> on fml coding style guide. + +=head1 AUTHOR + +Ken'ichi Fukamachi + +=head1 COPYRIGHT + +Copyright (C) 2003 Ken'ichi Fukamachi + +All rights reserved. This program is free software; you can +redistribute it and/or modify it under the same terms as Perl itself. + +=head1 HISTORY + +FML::Install appeared in fml8 mailing list driver package. +See C<http://www.fml.org/> for more details. + +=cut + + +1; diff --git a/install.pl.in b/install.pl.in new file mode 100755 index 00000000..9c3f413f --- /dev/null +++ b/install.pl.in @@ -0,0 +1,85 @@ +#! @PERL@ -w +#-*- perl -*- +# +# Copyright (C) 2003 Ken'ichi Fukamachi +# All rights reserved. This program is free software; you can +# redistribute it and/or modify it under the same terms as Perl itself. +# +# $FML$ +# + +use strict; +use Carp; +use lib qw(fml/lib cpan/lib img/lib); + +# Run this from the top-level fml source directory. +$ENV{'PATH'} = '/usr/xpg4/bin:/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc'; + +my $debug = 0; + +if ($0 eq __FILE__) { + umask(022); + + unless (@ARGV) { + croak("Usage: $0 install.cf\n"); + } + else { + _install( $ARGV[0] ); + } +} +else { + croak("Usage: $0 install.cf\n"); +} + +exit 0; + + +# Descriptions: install fml8 +# Arguments: STR($cf) +# Side Effects: install a lot of files: bin, lib, libexec/ and share/. +# Return Value: none +sub _install +{ + my ($cf) = @_; + my $format = "%20s = %s\n"; + + use FML::Install; + my $installer = new FML::Install; + my $config = $installer->load_install_cf( $cf ); + + printf $format, "version", $installer->get_version() if $debug; + + my $list = $config->get_as_array_ref('mandatory_dirs'); + for my $dir (@$list) { + my $path = $installer->path($dir); + printf $format, $dir, $path if $debug; + unless (-d $path) { + $installer->mkdir($path); + } + else { + print STDERR "ok $path\n" if $debug; + } + } + + # XXX-TODO: check uid, gid + + $installer->install_main_cf(); + $installer->install_sample_cf_files(); + $installer->install_default_config_files(); + $installer->install_mtree_dir(); + $installer->install_lib_dir(); + $installer->install_libexec_dir(); + $installer->install_data_dir(); + + # install programs hereafter. + $installer->install_bin_programs(); + + # update loader. + if ( $installer->need_resymlink_loader() ) { + $installer->install_loader(); + $installer->resymlink_loader(); + } + + # set up ml_spool_dir such as /var/spool/ml if needed. + $installer->setup_ml_spool_dir(); +} |
