summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Conf.pm2
-rw-r--r--FS/FS/part_export.pm20
-rw-r--r--FS/FS/part_export/domain_shellcommands.pm18
-rw-r--r--FS/FS/part_export/forward_shellcommands.pm110
-rw-r--r--FS/FS/svc_domain.pm59
-rw-r--r--FS/FS/svc_forward.pm192
-rw-r--r--FS/MANIFEST2
-rw-r--r--FS/t/part_export-forward_shellcommands.t5
-rw-r--r--httemplate/docs/install.html16
9 files changed, 166 insertions, 258 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 545d8b7..d0ecf32 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -818,7 +818,7 @@ httemplate/docs/config.html
{
'key' => 'vpopmailmachines',
'section' => 'deprecated',
- 'description' => '<b>DEPRECATED</b>, add a <i>cp</i> <a href="../browse/part_export.cgi">export</a> instead. This option used to contain your vpopmail pop toasters, one per line. Each line is of the form "machinename vpopdir vpopuid vpopgid". For example: <code>poptoaster.domain.tld /home/vpopmail 508 508</code> Note: vpopuid and vpopgid are values taken from the vpopmail machine\'s /etc/passwd',
+ 'description' => '<b>DEPRECATED</b>, add a <i>vpopmail</i> <a href="../browse/part_export.cgi">export</a> instead. This option used to contain your vpopmail pop toasters, one per line. Each line is of the form "machinename vpopdir vpopuid vpopgid". For example: <code>poptoaster.domain.tld /home/vpopmail 508 508</code> Note: vpopuid and vpopgid are values taken from the vpopmail machine\'s /etc/passwd',
'type' => 'textarea',
},
diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index 4471d6e..f99dc63 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -815,6 +815,18 @@ tie my %ldap_options, 'Tie::IxHash',
'radius' => { label=>'Export RADIUS attributes', type=>'checkbox', },
;
+tie my %forward_shellcommands_options, 'Tie::IxHash',
+ 'user' => { lable=>'Remote username', default=>'root' },
+ 'useradd' => { label=>'Insert command',
+ default=>'',
+ },
+ 'userdel' => { label=>'Delete command',
+ default=>'',
+ },
+ 'usermod' => { label=>'Modify command',
+ default=>'',
+ },
+;
#export names cannot have dashes...
%exports = (
@@ -935,7 +947,7 @@ tie my %ldap_options, 'Tie::IxHash',
'domain_shellcommands' => {
'desc' => 'Run remote commands via SSH, for domains.',
'options' => \%domain_shellcommands_options,
- 'notes' => 'Run remote commands via SSH, for domains. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.',
+ 'notes' => 'Run remote commands via SSH, for domains. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.<BR><BR>Use these buttons for some useful presets:<UL><LI><INPUT TYPE="button" VALUE="qmail catchall .qmail-domain-default maintenance" onClick=\'this.form.useradd.value = "[ \"$uid\" -a \"$gid\" -a \"$dir\" -a \"$qdomain\" ] && [ -e $dir/.qmail-$qdomain-default ] || { touch $dir/.qmail-$qdomain-default; chown $uid:$gid $dir/.qmail-$qdomain-default; }"; this.form.userdel.value = ""; this.form.usermod.value = "";\'></UL>',
},
@@ -948,6 +960,12 @@ tie my %ldap_options, 'Tie::IxHash',
#'nodomain' => 'Y',
'notes' => 'Database schema can be made to work with Courier IMAP and Exim. Others could work but are untested. (...extended description from pc-intouch?...)',
},
+
+ 'forward_shellcommands' => {
+ 'desc' => 'Run remote commands via SSH, for forwards',
+ 'options' => \%forward_shellcommands_options,
+ 'notes' => 'Run remote commands via SSH, for forwards. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.<BR><BR>Use these buttons for some useful presets:<UL><LI><INPUT TYPE="button" VALUE="text vpopmail maintenance" onClick=\'this.form.useradd.value = "[ -d /home/vpopmail/domains/$domain/$username ] && { echo \"$destination\" > /home/vpopmail/domains/$domain/$username/.qmail; chown vpopmail:vchkpw /home/vpopmail/domains/$domain/$username/.qmail; }"; this.form.userdel.value = "rm /home/vpopmail/domains/$domain/$username/.qmail"; this.form.usermod.value = "mv /home/vpopmail/domains/$old_domain/$old_username/.qmail /home/vpopmail/domains/$new_domain/$new_username; [ \"$old_destination\" != \"$new_destination\" ] && { echo \"$new_destination\" > /home/vpopmail/domains/$new_domain/$new_username/.qmail; chown vpopmail:vchkpw /home/vpopmail/domains/$new_domain/$new_username/.qmail; }";\'></UL>',
+ },
},
'svc_www' => {
diff --git a/FS/FS/part_export/domain_shellcommands.pm b/FS/FS/part_export/domain_shellcommands.pm
index 5b3cd5d..5b100e8 100644
--- a/FS/FS/part_export/domain_shellcommands.pm
+++ b/FS/FS/part_export/domain_shellcommands.pm
@@ -28,17 +28,15 @@ sub _export_command {
no strict 'refs';
${$_} = $svc_domain->getfield($_) foreach $svc_domain->fields;
}
+ ( $qdomain = $domain ) =~ s/\./:/g; #see dot-qmail(5): EXTENSION ADDRESSES
-# my $domain_record = $svc_www->domain_record; # or die ?
-# my $zone = $domain_record->reczone; # or die ?
-# unless ( $zone =~ /\.$/ ) {
-# my $svc_domain = $domain_record->svc_domain; # or die ?
-# $zone .= '.'. $svc_domain->domain;
-# }
-
-# my $svc_acct = $svc_www->svc_acct; # or die ?
-# my $username = $svc_acct->username;
-# my $homedir = $svc_acct->dir; # or die ?
+ if ( $svc_domain->catchall ) {
+ no strict 'refs';
+ my $svc_acct = $svc_domain->catchall_svc_acct;
+ ${$_} = $svc_acct->getfield($_) foreach qw(uid gid dir);
+ } else {
+ ${$_} = '' foreach qw(uid gid dir);
+ }
#done setting variables for the command
diff --git a/FS/FS/part_export/forward_shellcommands.pm b/FS/FS/part_export/forward_shellcommands.pm
new file mode 100644
index 0000000..43d558a
--- /dev/null
+++ b/FS/FS/part_export/forward_shellcommands.pm
@@ -0,0 +1,110 @@
+package FS::part_export::forward_shellcommands;
+
+use strict;
+use vars qw(@ISA);
+use FS::part_export;
+
+@ISA = qw(FS::part_export);
+
+sub rebless { shift; }
+
+sub _export_insert {
+ my($self) = shift;
+ $self->_export_command('useradd', @_);
+}
+
+sub _export_delete {
+ my($self) = shift;
+ $self->_export_command('userdel', @_);
+}
+
+sub _export_command {
+ my ( $self, $action, $svc_forward ) = (shift, shift, shift);
+ my $command = $self->option($action);
+
+ #set variable for the command
+ no strict 'vars';
+ {
+ no strict 'refs';
+ ${$_} = $svc_forward->getfield($_) foreach $svc_forward->fields;
+ }
+
+ my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->srcsvc } );
+ $username = $svc_acct->username;
+ $domain = $svc_acct->domain;
+ if ($self->dstsvc) {
+ $destination = $self->dstsvc_acct->email;
+ } else {
+ $destination = $self->dst;
+ }
+
+ #done setting variables for the command
+
+ $self->shellcommands_queue( $svc_forward->svcnum,
+ user => $self->option('user')||'root',
+ host => $self->machine,
+ command => eval(qq("$command")),
+ );
+}
+
+sub _export_replace {
+ my( $self, $new, $old ) = (shift, shift, shift);
+ my $command = $self->option('usermod');
+
+ #set variable for the command
+ no strict 'vars';
+ {
+ no strict 'refs';
+ ${"old_$_"} = $old->getfield($_) foreach $old->fields;
+ ${"new_$_"} = $new->getfield($_) foreach $new->fields;
+ }
+
+ my $old_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->srcsvc } );
+ $old_username = $old_svc_acct->username;
+ $old_domain = $old_svc_acct->domain;
+ if ($self->dstsvc) {
+ $old_destination = $self->dstsvc_acct->email;
+ } else {
+ $old_destination = $self->dst;
+ }
+
+ my $new_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->srcsvc } );
+ $new_username = $new_svc_acct->username;
+ $new_domain = $new_svc_acct->domain;
+ if ($self->dstsvc) {
+ $new_destination = $self->dstsvc_acct->email;
+ } else {
+ $new_destination = $self->dst;
+ }
+
+ #done setting variables for the command
+
+ $self->shellcommands_queue( $new->svcnum,
+ user => $self->option('user')||'root',
+ host => $self->machine,
+ command => eval(qq("$command")),
+ );
+}
+
+#a good idea to queue anything that could fail or take any time
+sub shellcommands_queue {
+ my( $self, $svcnum ) = (shift, shift);
+ my $queue = new FS::queue {
+ 'svcnum' => $svcnum,
+ 'job' => "FS::part_export::forward_shellcommands::ssh_cmd",
+ };
+ $queue->insert( @_ );
+}
+
+sub ssh_cmd { #subroutine, not method
+ use Net::SSH '0.07';
+ &Net::SSH::ssh_cmd( { @_ } );
+}
+
+#sub shellcommands_insert { #subroutine, not method
+#}
+#sub shellcommands_replace { #subroutine, not method
+#}
+#sub shellcommands_delete { #subroutine, not method
+#}
+
diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm
index 3941d6e..81edc33 100644
--- a/FS/FS/svc_domain.pm
+++ b/FS/FS/svc_domain.pm
@@ -3,14 +3,13 @@ package FS::svc_domain;
use strict;
use vars qw( @ISA $whois_hack $conf $smtpmachine
@defaultrecords $soadefaultttl $soaemail $soaexpire $soamachine
- $soarefresh $soaretry $qshellmachine $nossh_hack
+ $soarefresh $soaretry
);
use Carp;
use Mail::Internet 1.44;
use Mail::Header;
use Date::Format;
use Net::Whois 1.0;
-use Net::SSH;
use FS::Record qw(fields qsearch qsearchs dbh);
use FS::Conf;
use FS::svc_Common;
@@ -37,9 +36,6 @@ $FS::UID::callback{'FS::domain'} = sub {
$soarefresh = $conf->config('soarefresh');
$soaretry = $conf->config('soaretry');
- $qshellmachine = $conf->exists('qmailmachines')
- ? $conf->config('shellmachine')
- : '';
};
=head1 NAME
@@ -120,21 +116,6 @@ If any records are defined in the I<defaultrecords> configuration file,
appropriate records are added to the domain_record table (see
L<FS::domain_record>).
-If a machine is defined in the I<shellmachine> configuration value, the
-I<qmailmachines> configuration file exists, and the I<catchall> field points
-to an an account with a home directory (see L<FS::svc_acct>), the command:
-
- [ -e $dir/.qmail-$qdomain-defualt ] || {
- touch $dir/.qmail-$qdomain-default;
- chown $uid:$gid $dir/.qmail-$qdomain-default;
- }
-
-is executed on shellmachine via ssh (see L<dot-qmail/"EXTENSION ADDRESSES">).
-This behaviour can be supressed by setting $FS::svc_domain::nossh_hack true.
-
-a machine is defined
-in the
-
=cut
sub insert {
@@ -211,28 +192,6 @@ sub insert {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
- if ( $qshellmachine && $self->catchall && ! $nossh_hack ) {
-
- my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->catchall } )
- or warn "WARNING: inserted unknown catchall: ". $self->catchall;
- if ( $svc_acct && $svc_acct->dir ) {
- my $qdomain = $self->domain;
- $qdomain =~ s/\./:/g; #see manpage for 'dot-qmail': EXTENSION ADDRESSES
- my ( $uid, $gid, $dir ) = (
- $svc_acct->uid,
- $svc_acct->gid,
- $svc_acct->dir,
- );
-
- my $queue = new FS::queue {
- 'svcnum' => $self->svcnum,
- 'job' => 'Net::SSH::ssh_cmd',
- };
- $error = $queue->insert("root\@$qshellmachine", "[ -e $dir/.qmail-$qdomain-default ] || { touch $dir/.qmail-$qdomain-default; chown $uid:$gid $dir/.qmail-$qdomain-default; }" );
-
- }
- }
-
''; #no error
}
@@ -411,6 +370,15 @@ sub domain_record {
}
+sub catchall_svc_acct {
+ my $self = shift;
+ if ( $self->catchall ) {
+ qsearchs( 'svc_acct', { 'svcnum' => $self->catchall } );
+ } else {
+ '';
+ }
+}
+
=item whois
Returns the Net::Whois::Domain object (see L<Net::Whois>) for this domain, or
@@ -449,8 +417,6 @@ sub submit_internic {
=head1 BUGS
-All BIND/DNS fields should be included (and exported).
-
Delete doesn't send a registration template.
All registries should be supported.
@@ -462,9 +428,8 @@ The $recref stuff in sub check should be cleaned up.
=head1 SEE ALSO
L<FS::svc_Common>, L<FS::Record>, L<FS::Conf>, L<FS::cust_svc>,
-L<FS::part_svc>, L<FS::cust_pkg>, L<Net::Whois>, L<ssh>,
-L<dot-qmail>, schema.html from the base documentation, config.html from the
-base documentation.
+L<FS::part_svc>, L<FS::cust_pkg>, L<Net::Whois>, schema.html from the base
+documentation, config.html from the base documentation.
=cut
diff --git a/FS/FS/svc_forward.pm b/FS/FS/svc_forward.pm
index 1c5b5c4..2b1fb92 100644
--- a/FS/FS/svc_forward.pm
+++ b/FS/FS/svc_forward.pm
@@ -1,9 +1,7 @@
package FS::svc_forward;
use strict;
-use vars qw( @ISA $nossh_hack $conf $shellmachine @qmailmachines
- @vpopmailmachines );
-use Net::SSH qw(ssh);
+use vars qw( @ISA );
use FS::Conf;
use FS::Record qw( fields qsearch qsearchs dbh );
use FS::svc_Common;
@@ -13,21 +11,6 @@ use FS::svc_domain;
@ISA = qw( FS::svc_Common );
-#ask FS::UID to run this stuff for us later
-$FS::UID::callback{'FS::svc_forward'} = sub {
- $conf = new FS::Conf;
- if ( $conf->exists('qmailmachines') ) {
- $shellmachine = $conf->config('shellmachine')
- } else {
- $shellmachine = '';
- }
- if ( $conf->exists('vpopmailmachines') ) {
- @vpopmailmachines = $conf->config('vpopmailmachines');
- } else {
- @vpopmailmachines = ();
- }
-};
-
=head1 NAME
FS::svc_forward - Object methods for svc_forward records
@@ -91,17 +74,6 @@ the error, otherwise returns false.
The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
defined. An FS::cust_svc record will be created and inserted.
-If the configuration value (see L<FS::Conf>) vpopmailmachines exists, then
-the command:
-
- [ -d $vpopdir/domains/$domain/$source ] && {
- echo "$destination" >> $vpopdir/domains/$domain/$username/.$qmail
- chown $vpopuid:$vpopgid $vpopdir/domains/$domain/$username/.$qmail
- }
-
-is executed on each vpopmailmachine via ssh (see the vpopmail documentation).
-This behaviour can be supressed by setting $FS::svc_forward::nossh_hack true.
-
=cut
sub insert {
@@ -128,32 +100,6 @@ sub insert {
return $error;
}
- my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->srcsvc } );
- my $username = $svc_acct->username;
- my $domain = $svc_acct->domain;
- my $destination;
- if ($self->dstsvc) {
- $destination = $self->dstsvc_acct->email;
- } else {
- $destination = $self->dst;
- }
-
- foreach my $vpopmailmachine ( @vpopmailmachines ) {
- my($machine, $vpopdir, $vpopuid, $vpopgid) = split(/\s+/, $vpopmailmachine);
- my $queue = new FS::queue {
- 'svcnum' => $self->svcnum,
- 'job' => 'Net::SSH::ssh_cmd',
- };
- # should be neater
- my $error = $queue->insert("root\@$machine","[ -d $vpopdir/domains/$domain/$username ] && { echo \"$destination\" >> $vpopdir/domains/$domain/$username/.qmail; chown $vpopuid:$vpopgid $vpopdir/domains/$domain/$username/.qmail; }")
- unless $nossh_hack;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "queueing job (transaction rolled back): $error";
- }
-
- }
-
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
''; #no error
@@ -166,19 +112,6 @@ returns the error, otherwise returns false.
The corresponding FS::cust_svc record will be deleted as well.
-If the configuration value vpopmailmachines exists, then the command:
-
- { sed -e '/^$destination/d' <
- $vpopdir/domains/$srcdomain/$srcusername/.qmail >
- $vpopdir/domains/$srcdomain/$srcusername/.qmail.temp;
- mv $vpopdir/domains/$srcdomain/$srcusername/.qmail.temp
- $vpopdir/domains/$srcdomain/$srcusername/.qmail;
- chown $vpopuid.$vpopgid $vpopdir/domains/$srcdomain/$srcusername/.qmail; }
-
-
-is executed on each vpopmailmachine via ssh. This behaviour can be supressed
-by setting $FS::svc_forward_nossh_hack true.
-
=cut
sub delete {
@@ -201,37 +134,6 @@ sub delete {
return $error;
}
- my $svc_acct = $self->srcsvc_acct;
- my $username = $svc_acct->username;
- my $domain = $svc_acct->domain;
- my $destination;
- if ($self->dstsvc) {
- $destination = $self->dstsvc_acct->email;
- } else {
- $destination = $self->dst;
- }
- foreach my $vpopmailmachine ( @vpopmailmachines ) {
- my($machine, $vpopdir, $vpopuid, $vpopgid) =
- split(/\s+/, $vpopmailmachine);
- my $queue = new FS::queue { 'job' => 'Net::SSH::ssh_cmd' };
- # should be neater
- my $error = $queue->insert("root\@$machine",
- "sed -e '/^$destination/d' " .
- "< $vpopdir/domains/$domain/$username/.qmail" .
- "> $vpopdir/domains/$domain/$username/.qmail.temp; " .
- "mv $vpopdir/domains/$domain/$username/.qmail.temp " .
- "$vpopdir/domains/$domain/$username/.qmail; " .
- "chown $vpopuid.$vpopgid $vpopdir/domains/$domain/$username/.qmail;"
- )
- unless $nossh_hack;
-
- if ($error ) {
- $dbh->rollback if $oldAutoCommit;
- return "queueing job (transaction rolled back): $error";
- }
-
- }
-
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
}
@@ -242,29 +144,6 @@ sub delete {
Replaces OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
-If the configuration value vpopmailmachines exists, then the command:
-
- { sed -e '/^$destination/d' <
- $vpopdir/domains/$srcdomain/$srcusername/.qmail >
- $vpopdir/domains/$srcdomain/$srcusername/.qmail.temp;
- mv $vpopdir/domains/$srcdomain/$srcusername/.qmail.temp
- $vpopdir/domains/$srcdomain/$srcusername/.qmail;
- chown $vpopuid.$vpopgid $vpopdir/domains/$srcdomain/$srcusername/.qmail; }
-
-
-is executed on each vpopmailmachine via ssh. This behaviour can be supressed
-by setting $FS::svc_forward_nossh_hack true.
-
-Also, if the configuration value vpopmailmachines exists, then the command:
-
- [ -d $vpopdir/domains/$domain/$source ] && {
- echo "$destination" >> $vpopdir/domains/$domain/$username/.$qmail
- chown $vpopuid:$vpopgid $vpopdir/domains/$domain/$username/.$qmail
- }
-
-is executed on each vpopmailmachine via ssh. This behaviour can be supressed
-by setting $FS::svc_forward_nossh_hack true.
-
=cut
sub replace {
@@ -295,66 +174,6 @@ sub replace {
return $error;
}
- my $old_svc_acct = $old->srcsvc_acct;
- my $old_username = $old_svc_acct->username;
- my $old_domain = $old_svc_acct->domain;
- my $destination;
- if ($old->dstsvc) {
- $destination = $old->dstsvc_acct->email;
- } else {
- $destination = $old->dst;
- }
- foreach my $vpopmailmachine ( @vpopmailmachines ) {
- my($machine, $vpopdir, $vpopuid, $vpopgid) =
- split(/\s+/, $vpopmailmachine);
- my $queue = new FS::queue {
- 'svcnum' => $new->svcnum,
- 'job' => 'Net::SSH::ssh_cmd',
- };
- # should be neater
- my $error = $queue->insert("root\@$machine",
- "sed -e '/^$destination/d' " .
- "< $vpopdir/domains/$old_domain/$old_username/.qmail" .
- "> $vpopdir/domains/$old_domain/$old_username/.qmail.temp; " .
- "mv $vpopdir/domains/$old_domain/$old_username/.qmail.temp " .
- "$vpopdir/domains/$old_domain/$old_username/.qmail; " .
- "chown $vpopuid.$vpopgid " .
- "$vpopdir/domains/$old_domain/$old_username/.qmail;"
- )
- unless $nossh_hack;
-
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "queueing job (transaction rolled back): $error";
- }
- }
-
- #false laziness with stuff in insert, should subroutine
- my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $new->srcsvc } );
- my $username = $svc_acct->username;
- my $domain = $svc_acct->domain;
- if ($new->dstsvc) {
- $destination = $new->dstsvc_acct->email;
- } else {
- $destination = $new->dst;
- }
-
- foreach my $vpopmailmachine ( @vpopmailmachines ) {
- my($machine, $vpopdir, $vpopuid, $vpopgid) = split(/\s+/, $vpopmailmachine);
- my $queue = new FS::queue {
- 'svcnum' => $new->svcnum,
- 'job' => 'Net::SSH::ssh_cmd',
- };
- # should be neater
- my $error = $queue->insert("root\@$machine","[ -d $vpopdir/domains/$domain/$username ] && { echo \"$destination\" >> $vpopdir/domains/$domain/$username/.qmail; chown $vpopuid:$vpopgid $vpopdir/domains/$domain/$username/.qmail; }")
- unless $nossh_hack;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "queueing job (transaction rolled back): $error";
- }
- }
- #end subroutinable bits
-
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
}
@@ -450,19 +269,12 @@ sub dstsvc_acct {
=back
-=head1 VERSION
-
-$Id: svc_forward.pm,v 1.12 2002-05-31 17:50:37 ivan Exp $
-
=head1 BUGS
-The remote commands should be configurable.
-
=head1 SEE ALSO
L<FS::Record>, L<FS::Conf>, L<FS::cust_svc>, L<FS::part_svc>, L<FS::cust_pkg>,
-L<FS::svc_acct>, L<FS::svc_domain>, L<Net::SSH>, L<ssh>, L<dot-qmail>,
-schema.html from the base documentation.
+L<FS::svc_acct>, L<FS::svc_domain>, schema.html from the base documentation.
=cut
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 32a4e4f..6397cc4 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -73,6 +73,7 @@ FS/part_export/bsdshell.pm
FS/part_export/cp.pm
FS/part_export/cyrus.pm
FS/part_export/domain_shellcommands.pm
+FS/part_export/forward_shellcommands.pm
FS/part_export/http.pm
FS/part_export/infostreet.pm
FS/part_export/ldap.pm
@@ -155,6 +156,7 @@ t/part_export-bsdshell.t
t/part_export-cp.t
t/part_export-cyrus.t
t/part_export-domain_shellcommands.t
+t/part_export-forward_shellcommands.t
t/part_export-http.t
t/part_export-infostreet.t
t/part_export-ldap.t
diff --git a/FS/t/part_export-forward_shellcommands.t b/FS/t/part_export-forward_shellcommands.t
new file mode 100644
index 0000000..78ca68d
--- /dev/null
+++ b/FS/t/part_export-forward_shellcommands.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::part_export::forward_shellcommands;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html
index 51dce4d..ed419a1 100644
--- a/httemplate/docs/install.html
+++ b/httemplate/docs/install.html
@@ -13,9 +13,9 @@ Before installing, you need:
<li>A <b>transactional</b> database engine <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">supported</a> by Perl's <a href="http://dbi.perl.org">DBI</a>.
<ul>
<li><a href="http://www.postgresql.org/">PostgreSQL</a> is recommended (v7or later).
- <li>MySQL versions before 4.1 do not support standard SQL subqueries and are <b>NOT SUPPORTED</b>. If you are a developer who wishes to contribute MySQL 3.x/4.0 support, see <a href="http://pouncequick.420.am/rt/Ticket/Display.html?id=438">ticket #438</a> in the bug-tracking system and ask on the -devel mailing list.
-<!-- <li>MySQL has been reported to work.
- <b>MySQL's default <a href="http://www.mysql.com/doc/M/y/MyISAM.html">MyISAM</a> and <a href="http://www.mysql.com/doc/I/S/ISAM.html">ISAM</a> table types are not supported</b>. If you want to use MySQL, you <b>must</b> use one of the new <a href="http://www.mysql.com/doc/T/a/Table_types.html">transaction-safe table types</a> such as <a href="http://www.mysql.com/doc/B/D/BDB.html">BDB</a> or <a href="http://www.mysql.com/doc/I/n/InnoDB.html">InnoDB</a>, and set it as the default table type using the <code>--default-table-type=BDB</code> or <code>--default-table-type=InnoDB</code> <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Command-line_options">mysqld command-line option</a> or by setting <code>default-table-type=BDB</code> or <code>default-table-type=InnoDB</code> in the <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Option_files">my.cnf option file</a>. -->
+ <li><a href="http://www.mysql.com/">MySQL</a> <b>MINIMUM VERSION 4.1</b> is untested but may work. Versions before 4.1 do not support standard SQL subqueries and are <b>NOT SUPPORTED</b>. If you are a developer who wishes to contribute MySQL 3.x/4.0 support, see <a href="http://pouncequick.420.am/rt/Ticket/Display.html?id=438">ticket #438</a> in the bug-tracking system and ask on the -devel mailing list.
+<!-- <li>MySQL has been reported to work. -->
+ <b>MySQL's default <a href="http://www.mysql.com/doc/M/y/MyISAM.html">MyISAM</a> and <a href="http://www.mysql.com/doc/I/S/ISAM.html">ISAM</a> table types are not supported</b>. If you want to use MySQL, you <b>must</b> use one of the new <a href="http://www.mysql.com/doc/T/a/Table_types.html">transaction-safe table types</a> such as <a href="http://www.mysql.com/doc/B/D/BDB.html">BDB</a> or <a href="http://www.mysql.com/doc/I/n/InnoDB.html">InnoDB</a>, and set it as the default table type using the <code>--default-table-type=BDB</code> or <code>--default-table-type=InnoDB</code> <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Command-line_options">mysqld command-line option</a> or by setting <code>default-table-type=BDB</code> or <code>default-table-type=InnoDB</code> in the <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Option_files">my.cnf option file</a>.
</ul>
<li>Perl modules (<a href="http://theoryx5.uwinnipeg.ca/CPAN/perl/CPAN.html">CPAN</a> will query, download and build perl modules automatically)
<ul>
@@ -41,7 +41,7 @@ Before installing, you need:
<li><a href="http://search.cpan.org/search?dist=String-Approx">String-Approx</a>
<li><a href="http://search.cpan.org/search?dist=Text-Template">Text-Template</a>
<li><a href="http://search.cpan.org/search?dist=DBI">DBI</a>
- <li><a href="http://search.cpan.org/search?mode=module&query=DBD">DBD for your database engine</a> (<a href="http://search.cpan.org/search?dist=DBD-Pg">DBD::Pg</a> for PostgreSQL<!--, <a href="http://search.cpan.org/search?dist=DBD-mysql">DBD::mysql</a> for MySQL-->)
+ <li><a href="http://search.cpan.org/search?mode=module&query=DBD">DBD for your database engine</a> (<a href="http://search.cpan.org/search?dist=DBD-Pg">DBD::Pg</a> for PostgreSQL, <a href="http://search.cpan.org/search?dist=DBD-mysql">DBD::mysql</a> for MySQL)
<li><a href="http://search.cpan.org/search?dist=DBIx-DataSource">DBIx-DataSource</a>
<li><a href="http://search.cpan.org/search?dist=DBIx-DBSchema">DBIx-DBSchema</a>
<li><a href="http://search.cpan.org/search?dist=Net-SSH">Net-SSH</a>
@@ -72,17 +72,16 @@ Enter it again:
Shall the new user be allowed to create databases? (y/n) y
Shall the new user be allowed to create more new users? (y/n) n
CREATE USER</pre>
-<!-- <li> with <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#User_Account_Management">MySQL</a>:
+ <li> with <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#User_Account_Management">MySQL</a>:
<pre>
$ mysqladmin -u root password '<i>set_a_root_database_password</i>'
$ mysql -u root -p
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,INDEX,ALTER,CREATE,DROP on freeside.* TO freeside@localhost IDENTIFIED BY '<i>set_a_freeside_database_password</i>';</pre>
--->
</ul>
<!-- <li>Unpack the tarball: <pre>gunzip -c fs-x.y.z.tar.gz | tar xvf -</pre>-->
<li>Edit the top-level Makefile:
<ul>
- <li>Set <tt>DATASOURCE</tt> to your <a href="http://search.cpan.org/doc/TIMB/DBI-1.28/DBI.pm">DBI data source</a>, for example, <tt>DBI:Pg:dbname=freeside</tt> for PostgresSQL<!-- or <tt>DBI:mysql:freeside</tt> for MySQL-->. See the <a href="http://search.cpan.org/doc/TIMB/DBI-1.28/DBI.pm">DBI manpage</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">manpage for your DBD</a> for the exact syntax of your DBI data source.
+ <li>Set <tt>DATASOURCE</tt> to your <a href="http://search.cpan.org/doc/TIMB/DBI-1.28/DBI.pm">DBI data source</a>, for example, <tt>DBI:Pg:dbname=freeside</tt> for PostgresSQL or <tt>DBI:mysql:freeside</tt> for MySQL. See the <a href="http://search.cpan.org/doc/TIMB/DBI-1.28/DBI.pm">DBI manpage</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">manpage for your DBD</a> for the exact syntax of your DBI data source.
<li>Set <tt>DB_PASSWORD</tt> to the freeside database user's password.
</ul>
<li>Add the freeside database to your database engine:
@@ -93,10 +92,9 @@ $ su
<pre>
$ su freeside
$ createdb freeside</pre>
-<!-- (with MySQL:)
+ (with MySQL:)
<pre>
$ mysqladmin -u freeside -p create freeside </pre>
--->
<li>Build and install the Perl modules:
<pre>
$ make perl-modules