ichatserver_init_tool [plain text]
use Getopt::Std;
use File::Basename;
$g_my_name = "ichatserver_init_tool";
$g_jabber_var_dir = "/private/var/jabberd";
$g_db_dir = "$g_jabber_var_dir/sqlite";
$g_default_db_file = "$g_db_dir/jabberd2.db";
$g_db_setup_file = "$g_jabber_var_dir/db-setup.sqlite";
$g_conf_dir = "/private/etc/jabberd";
$g_tmp_dir = "$g_jabber_var_dir/tmp";
$g_pid_dir = "/private/var/run/jabberd";
$g_spool_dir = "/private/var/spool";
$g_log_dir = "$g_jabber_var_dir/log";
$g_logfile = "$g_log_dir/$g_my_name.log";
$g_sqlite3_path = "/usr/bin/sqlite3";
$g_jabber_user = 'jabber';
$g_jabber_group = 'jabber';
$g_admin_group = 'wheel';
$g_jabber_uid = getpwnam($g_jabber_user);
$g_jabber_gid = getgrnam($g_jabber_group);
$g_admin_gid = getgrnam($g_admin_group);
$DEBUG = 0;
$VERBOSE = 1;
$LOGGING = 1;
sub _usage() {
print "$g_my_name: tool for initializing the iChat Server sqlite database and initializing jabberd config files\n";
print "Usage:\n";
print "$g_my_name: [-d]\n";
print "Options:\n";
print " -d: debug mode\n";
print " -i: install db, create jabberd pid dir, and configure config files (set hostname and router random router passwords)\n";
print " -s: install sqlite database only\n";
print " -c: configure config files (set hostname and router random router passwords) only\n";
print " -p <path> : specify the full path for the jabberd database file. (Default: $g_default_db_file)\n";
print "\n";
}
sub _timestamp()
{
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
localtime(time);
$year += 1900;
$mon += 1;
if ( $hour =~ /^\d$/ ) { $hour = "0" . $hour; }
if ( $min =~ /^\d$/ ) { $min = "0" . $min; }
if ( $sec =~ /^\d$/ ) { $sec = "0" . $sec; }
my $ret = $year."-".$mon."-".$mday."-$hour:$min:$sec";
return $ret;
}
sub _log() {
my $t = &_timestamp;
if ($LOGGING) {
open(LOG, ">>$g_logfile") || die "ERROR: could not open log file at $g_logfile: $!";
print LOG "$t: $_[0]\n";
}
if ($VERBOSE) { print "$t: $_[0]\n"; }
}
sub _bail() {
&_log($_[0]);
exit 1;
}
sub random_password_gen() {
if ($_[0] !~ /^\d+$/) {
&_log("Invalid argument provided to random_password_gen(). Must be a valid non-negative integer.");
return "";
}
my $length = $_[0];
my $dev = "/dev/random";
my $password = "";
my $matchlist= q{ABCDEFGHIJKLMNOPQRSTUVWXYZJabcdefghijklmnopqrstuvwxyz0123456789`~!#$%^*()-=_+[]\\|;':",./?}.'{}';
my $random_bits;
&_log("Generating random password...");
eval {
$random_bits = sprintf("%0.0f", log(length($matchlist) ** $length) / log(2));
};
$matchlist =~ s|([^A-Za-z0-9])|\\$1|g;
if (! open(DEV, "<$dev")) {
&_log("Can't open random device $dev ($!)");
return "";
}
until ($password =~ /^.{$length}$/) {
$_ = getc DEV;
$password .= $_ if (m/[$matchlist]/);
}
&_log("Generated random password...");
close(DEV);
return $password;
}
# Create pid directory used by proxy and jabberd
sub init_pid_dir() {
if (! -e $g_pid_dir) {
&_log("Creating pid directory $g_pid_dir...");
if (! mkdir($g_pid_dir, 0775)) {
&_log("Unable to create directory $g_pid_dir ($!)");
return 1;
}
chown($g_jabber_uid, $g_jabber_gid, $g_pid_dir);
} else {
&_log("Directory already exists: $g_pid_dir");
}
return 0;
}
# Create spool dir for mu-conference
sub init_muc_spool_dir() {
my $hostname = `hostname`;
chomp($hostname);
my $full_spool_path = $g_spool_dir."/conference.".$hostname;
if (! -e $full_spool_path) {
&_log("Creating MUC spool directory $full_spool_path...");
if (! mkdir($full_spool_path, 0770)) {
&_log("Unable to create directory $full_spool_path ($!)");
return 1;
}
chown($g_jabber_uid, $g_jabber_gid, $full_spool_path);
} else {
&_log("Directory already exists: $full_spool_path");
}
return 0;
}
# Initialize sqlite database file for jabberd.
# returns:
# 0: success
# 1: error
# 2: database file already exists
#
sub init_db() {
my $db_file = shift;
&_log("Creating SQLite database setup for jabberd...");
if (! defined($db_file)) {
$db_file = $g_default_db_file;
}
if (-e "$db_file") {
&_log("Already exists: $db_file");
return 2;
}
my $db_containing_dir = dirname($db_file);
if (! -d $db_containing_dir) {
&_log("$db_containing_dir does not exist. Creating...");
if (! mkdir($db_containing_dir, 0750)) {
&_log("Cannot create directory: $db_containing_dir ... Aborting ($!)");
return 1;
}
}
my $ret = chown($g_jabber_uid, $g_jabber_gid, $db_containing_dir);
unless ($ret) {
&_log("Failed to set correct ownership on $db_containing_dir ($!)");
return 1;
}
if (! -e $g_db_setup_file) {
&_log("Cannot find: $g_db_setup_file");
return 1;
}
if (! -e $g_sqlite3_path) {
&_log("$g_sqlite3_path does not exist. Aborting.");
return 1;
}
$exec_string = "\"$g_sqlite3_path\" \"$db_file\" < \"$g_db_setup_file\"";
my $mask = umask;
umask(027);
$ret = system($exec_string);
umask($mask);
if ($ret != 0) {
&_log("Execution failed with status $ret: $exec_string ($!)");
return 1;
}
$ret = chown($g_jabber_uid, $g_jabber_gid, $db_file);
unless ($ret) {
&_log("Failed to set correct ownership on $db_file ($!)");
return 1;
}
return 0;
}
sub init_configs() {
my @lines;
my $line;
my @files = ("c2s.xml",
"sm.xml",
"s2s.xml",
"resolver.xml",
"router.xml",
"router-users.xml",
"muc-jcr.xml"
);
my $file;
my $hostname = `hostname`;
my $router_password = &random_password_gen(15);
if ($router_password eq "") {
&_log("random_password_gen failed, aborting");
return 1;
}
chomp($hostname);
foreach $file (@files) {
if (! open(FILE, "<$g_conf_dir/$file")) {
&_log("Could not open file: $g_conf_dir/$file ($!)");
return 1;
}
@lines = <FILE>;
close(FILE);
my $mask = umask;
umask(077);
if (! open(NEW_FILE, ">$g_tmp_dir/$file.new")) {
umask($mask);
&_log("Could not open file: $g_tmp_dir/$file.new ($!)");
return 1;
}
umask($mask);
foreach $line (@lines) {
if ($line =~ /\@HOSTNAME\@/) {
&_log("Found hostname tag in $g_conf_dir/$file, replacing string with $hostname...");
$line =~ s/\@HOSTNAME\@/$hostname/g;
}
if ($line =~ /\@ROUTERPASSWORD\@/) {
&_log("Found password tag in $g_conf_dir/$file, replacing string...");
$line =~ s/\@ROUTERPASSWORD\@/$router_password/g;
}
print NEW_FILE "$line";
}
close(NEW_FILE);
$mask = umask;
umask(077);
my $ret = rename("$g_tmp_dir/$file.new", "$g_conf_dir/$file");
umask($mask);
unless ($ret) {
&_log("rename failed with status $ret: ($!)");
return 1;
}
# Set the ownership and permissions for the file
$ret = chown($g_jabber_uid, $g_admin_gid, "$g_conf_dir/$file");
unless ($ret) {
&_log("chown failed with status $ret: ($!)");
}
$ret = chmod(0600, "$g_conf_dir/$file");
unless ($ret) {
&_log("chmod failed with status $ret: ($!)");
}
}
return 0;
}
####### MAIN
getopts('discp:?h', \%opts);
if (defined $opts{'d'}) {
$DEBUG = 1;
}
if (defined $opts{'?'} || defined $opts{'h'}) {
&_usage;
exit 0;
}
my $db_file;
if (defined $opts{'p'}) {
$db_file = $opts{'p'};
}
if (defined $opts{'i'}) {
$ret = &init_pid_dir;
if ($ret > 0) {
&_bail("Exiting because pid dir could not be created");
}
$ret = &init_muc_spool_dir;
if ($ret > 0) {
&_bail("Exiting because muc spool dir could not be created");
}
$ret = &init_db($db_file);
if ($ret == 2) {
&_log("Exiting since database already exists. Use -c to init config files only.");
exit 0;
} elsif ($ret == 1) {
&_bail("Aborting since init_db failed.");
}
$ret = &init_configs;
if ($ret > 0) {
&_bail("Aborting since init_configs failed.");
}
} elsif (defined $opts{'s'}) {
$ret = &init_db($db_file);
if ($ret == 1) {
&_bail("Aborting since init_db failed.");
}
} elsif (defined $opts{'c'}) {
$ret = &init_configs;
if ($ret > 0) {
&_bail("Aborting since init_configs failed.");
}
} else {
&_log("Unrecognized options, exiting");
&_usage;
exit 1;
}
&_log("Finished.");