#!/usr/bin/perl #*************************************************************************** # Virtfs - A Perl/Dialog Script # ------------------- # Started : December 09 1999 # This Version : v. 0.70.2 - April 4 2001 # copyright : (C) 1999-2001 by Afra Ahmad # email : afra@prongs.org # homepage : http://www.prongs.org/virtfs # documentation : http://www.prongs.org/virtfs/docs # *************************************************************************** #*************************************************************************** # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # *************************************************************************** use strict; &root_check(); # check that only root is running this. my $config_file="/etc/virt.conf"; # The configuration file - this is the important one! my $template_conf="/etc/virt_template.conf"; # The configuration file for the template directory my $version="0.70.2"; # The current version number die "$template_conf not found!" if (!-e $template_conf); die "$config_file not found!" if (!-e $config_file); # chroot must be in the following directories. $ENV{'PATH'} = "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/lib"; my $chroot="chroot"; # the chroot command should be in one of the directories above in $ENV{'PATH'} # collect values of the variables needed by Virtfs, from the config. file my $config_variables=&read_config($config_file); my $dialog = $config_variables->{"Dialog"}; # The external program to use for the UI. my $tmp=$config_variables->{"Temp Directory"}; # directory to keep logs and temporary files in. my $default_shell=$config_variables->{"Default Shell"}; #default shells to assign users. my $default_home=$config_variables->{"Default Home Directory"}; #default home dir. location, ie. /home my $apache_conf=$config_variables->{"Apache Conf"}; # where Apache's httpd.conf resides. my $logoption=$config_variables->{"Log"}; # If we should log actions into the logfile. my $virtual_dir=$config_variables->{"Leading Virtual Directory"}; # where the virtual servers reside. my $server_file=$config_variables->{"Servers File"}; # the file with info. on all virtual servers. my $smail =$config_variables->{"Use Sendmail"}; # Does our system use Sendmail? my $copy_file=$config_variables->{"Copy Script"}; # the copy system commands. my $delete_root=$config_variables->{"Delete Root"}; # The root account my $ldconfig_libs=$config_variables->{"ldconfig libs"}; # the /etc/ld.so.conf contents my $sendmail_cf=$config_variables->{"Sendmail CF"}; # the main servers sendmail.cf my $sendmail_alias=$config_variables->{"Sendmail Aliases"}; # The aliases file my $ftp_config_files=$config_variables->{"ftp files"}; # The ftp config files my $ns1 = $config_variables->{"Primary DNS"}; my $ns2 = $config_variables->{"Secondary DNS"}; # Can the root account be removed or altered? $delete_root =~ tr/A-Z/a-z/; if ($delete_root =~ /yes/){ $delete_root = 0;} else { $delete_root = 1;} &check_required($config_variables); # check if all important variables are defined # Are we using Sendmail as a MTA? $smail =~ tr/A-Z/a-z/; if ($smail eq "yes"){$smail = 1;} else{$smail = 0;} my $sendmail = &find_path("sendmail"); $smail = 0 if (!$sendmail); my $mail_folder=$config_variables->{"Default Mail Folder"} if ($smail); my $mail_grp=$config_variables->{"Default Mail Group"} if ($smail); &check_sendmail_config($sendmail_cf) if ($smail); # check to see if sendmail.cf is there. $server_file="$virtual_dir/$server_file"; # where the info. for virtual servers reside. # remove trailing / from directory names that were retrieved from the conf file. $tmp =~ s:/$::; $default_home =~ s:/$::; $mail_folder =~ s:/$:: if ($smail); # Log file stuff my ($log,$logfile); $logoption =~ tr/A-Z/a-z/; if ($logoption eq "on"){ $log=1; $logfile=$config_variables->{"Log File"}; $logfile =~ s:/$::; # in case.. } my $backtitle="--backtitle \"Virtual Services - virtfs v.$version \""; # dialog stuff. my $ansfile="$tmp/virtfs.tmp"; # the temporary file used to retrieve user's input my $menu_title="\"Virtfs $version\""; # the title for the menus # locate the names of the FTP and Mail service files, ie. conf.pop and conf.ftp . my $ftp_file=$config_variables->{"FTP file"}; $ftp_file="$virtual_dir/$ftp_file"; my $pop_file=$config_variables->{"MAIL file"}; $pop_file="$virtual_dir/$pop_file"; if (!-d $virtual_dir){ # the virtual directory does not exist. # The user will have to create a template directory first and if needed, re-configure my $text = "The directory for your virtual servers, $virtual_dir does not exist!\n"; $text .= "This must mean you have not set up a template directory or your configuration is wrong.\n"; $text .= "Please make sure you run virt_template.pl before proceeding with virtfs.\n"; $text .= "Please check $config_file, $template_conf and try again...\n\n"; print $text; exit(0); } # Find out where the template directory is my $template_dir=&read_template_config($template_conf); $template_dir = $virtual_dir ."/".$template_dir; &parse_args(@ARGV); # parse arguments - needs to be done after the configuration file is read in. &clean_up_lists(); # Phew, all variables collected - Virtfs now begins .... # list the domains and get the user's response. my ($domainname,$ip)=&list_domains($virtual_dir); if ($domainname eq "Create"){ # user chose to create a server. Do so and then exit. &create_virt_domain; exit(0); } my $domain="$virtual_dir/$domainname"; my $passwd_file="$virtual_dir/$domainname/etc/passwd"; my $shell_file=$domain."/etc/shells"; &menu_list; # start the main menu for the specified domain. sub menu_list{ #show the menu, get the choice, and do what the user asks for. # cancel exits, btw... my ($choice,$ret_result); while (1){ &list_menu($domain); # display the menu $choice=&get_answer($ansfile,1); # get user's request last if (!$choice); $ret_result= &look_choice($choice); last if (!$ret_result); } &logit("clear") if ($log); # add a linebreak to the log for easier parsing. exit(0); # end program - user chose to quit. } sub detect_new{ # detect new servers. my @dirs=<$virtual_dir/*>; my ($found,$i,$server_dir,$dir); for ($i=0;$i<@dirs;$i++){ if ($dirs[$i] eq $template_dir){ print "$template_dir ignored [ template directory ]...\n"; next; } if (-d "$dirs[$i]/etc"){ $found=1; # print $dirs[$i]."\n"; # split the server name from the full path... $server_dir = $dirs[$i]; $server_dir =~ s/$virtual_dir//g,$server_dir; # remove the leading path name $server_dir =~ s/^\///; # remove the first / in the full path # print "Server_dir: ".$server_dir." and $dirs[$i]\n"; print $server_dir; &compare_server($server_dir,$dirs[$i]); } } &clean_up_lists; # clean up stale entries if ($found != 1) { print "No virtual servers found in $virtual_dir!\nPlease make sure configuration is set.\n"; exit(0); } } sub compare_server{ my ($server,$dir)=@_; my ($d,$ip_server,$found_entry); open (SD, $server_file); while (){ chomp; s/#.*//; s/^\s+//; s/\s+$//; ($d,$ip_server)=split(/\:/,$_); if ($server eq $d){ print " - detected and exists in configuration. IP: $ip_server"; $found_entry = 1; } } close (SD); if ($found_entry != 1){ $domain =~ s#.*/##; print " .. detected and does not exist\n"; print "Please enter the IP number for $server: "; my $ip=;chomp $ip; open (FH,"+>>$server_file"); print FH "$server:$ip\n"; close (FH); print "Added.\n"; } print "\n"; } sub clean_up_lists{ # Clean up the $server_file (server.lists) of old entries #print "\nNow trying to clean up stale entries in $server_file\n"; my ($d,$ip_server,$delete); open (SD, $server_file); while (){ chomp; s/#.*//; s/^\s+//; s/\s+$//; ($d,$ip_server)=split(/\:/,$_); if (!-d "$virtual_dir/$d/etc" && $d){ print "$d ( $virtual_dir/$d ) does not have a proper filesystem. Delete entry [y/n]: "; $delete=;chomp($delete); if ($delete =~ /[Yy]/){ &remove_server_entry($d); } } } close (SD); close (TMP); } sub conf_files{ # Find out if a domain is configured for a certain service # and display the results to the user. my ($conf)=@_; open (FD, "+< $conf"); my ($i,$s,$found); while (){ if ($_ =~ /$domain/){ $found=1; last; } } close (FD); return "Yes" if ($found); return "No"; } sub look_choice{ # We take the user input from the menu and execute accordingly... # To implement your own functions here (after adding an entry to the menu), make sure # that the return code from the function which is called, is caught in the variable $ans . # (if a 0 is returned to the &menu_list, the program will exit.) my ($choice)=@_; # get the result from what the user chose. my ($text,$ans); # Call the functions needed according to what the user requested. if ($choice eq "I"){ # simply display the server information... $text .= "Server Name: $domainname\n"; $text .= "Server IP: $ip\n"; $text .= "Server Directory: $domain\n"; my ($ftp)=&conf_files($ftp_file); $text .= "FTP Active: $ftp\n"; my ($mail)=&conf_files($pop_file); $text .= "Mail Active: $mail\n"; $ans=&info ($backtitle,$text,"15 65"); } elsif ($choice eq "G"){ #finger a list of accounts. my $finger=&find_path("finger"); # does finger exist? ($text)=&list_accounts($domain) if ($finger); $ans=&finger_account($text,$finger) if ($finger); } elsif ($choice eq "T"){ # Create a mail folder for a specified user. # If user has configured virt.conf to use with Sendmail, # we need to list all the users for the user to choose. if ($smail){ ($text)=&list_accounts($domain); $ans=&mail_folder($text); } else{ $ans=&text_box("Sendmail","Sendmail value in virt.conf is no.\nYou can't edit further!","21 62"); } } elsif ($choice eq "R"){ # delete the server. Ask the user twice for confirmation, # and if (s)he agrees, remove the entry and delete the # domain's directory. Use with caution!! $text .= "Remove Server?"; my $ynstatus=&yes_no ($backtitle,$text); if ($ynstatus == 0){ $text = "Are you sure?\n(last chance)"; $ynstatus=&yes_no($backtitle,$text); if ($ynstatus==0){ &remove_server_entry($domainname); system("rm -rf $domain"); &delete_conf_entry($ftp_file); &delete_conf_entry($pop_file); print "Server Deleted.....\n"; &logit("Server Deleted!") if ($log); return 0; #exit } } } elsif ($choice eq "C"){ # alter all configuration files to reflect the new domain name and IP address... my $text = "Please enter the domain name (server.com):\n"; my $newdomain=&input($backtitle,$text,"$domainname","12 55"); if (!$newdomain){ return 1; } $text = "Current IP: $ip\n"; my ($stat,$newip); do{ $newip=&input($backtitle,$text,"","12 55"); $stat=&check_ip_format($newip); return 1 if ($stat == 255); }until ($stat == 1); &remove_server_entry(); # remove old server entry from the servers.list file. &delete_conf_entry($ftp_file); &delete_conf_entry($pop_file); open (FH, "+>> $server_file"); print FH "$newdomain:$newip\n"; close (FH); system ("echo $newdomain > $domain/etc/HOSTNAME") if ($newdomain ne $domainname); system ("mv $domain $virtual_dir/$newdomain") if ($newdomain ne $domainname); print "\nServer name changed $newdomain.\nIP changed to $newip."; print "\nDirectory has been changed to reflect this.\n"; print "Re-configure IP aliasing and then reset FTP/Mail services through virtfs\n"; return 0; } elsif ($choice eq "U"){ # simply list all users. ($text)=&list_users($domain); $ans=&text_box("Users",$text,"20 60"); } elsif ($choice eq "S"){ # su over to the domain as a specific user (you will be asked). my $su = &find_path("su"); $ans = &su_exec($domain,$su) if ($su); } elsif ($choice eq "W"){ # about screen - just list general info about virtfs. $text="Virtfs $version\n"; $text .= "\nWritten by Afra Ahmad\n See http://www.prongs.org/virtfs for latest updates\n"; $ans=&text_box("About",$text,"10 62"); } elsif ($choice eq "A"){ # Add a user! my $adduser=&find_path("adduser"); $ans=&add_user($domain,$adduser) if $adduser; } elsif ($choice eq "P"){ # change the password for a specified user my $passwd = &find_path("passwd"); ($text)=&list_accounts($domain) if $passwd; $ans=&change_passwd($text,$domain,$passwd) if $passwd; } elsif ($choice eq "D"){ # Delete a user from a given list. my $userdel = &find_path("userdel"); ($text)=&list_accounts($domain) if $userdel; $ans = &delete_account($text,$domain,$userdel) if $userdel; } elsif($choice eq "F"){ # add/remove FTP service... $ans = &services($ftp_file,"FTP"); } elsif($choice eq "M"){ # add/remove MAIL service. $ans = &services("$pop_file","Mail"); } elsif ($choice eq "L"){ $ans = &list_all(); } elsif($choice eq "H"){ # Help. I do plan on adding this soon..though, online help is available. my $text="Please read the online documentation\n at http://www.prongs.org/virtfs/docs/\n"; $ans=&text_box("HELP",$text,"12 60"); } elsif($choice eq "Q"){ # view Sendmail queue. my $exec=`$chroot $domain $sendmail -bp &1`; if ($?) { &error("Error!:\n$exec");return;} $ans=&text_box("Mail Queue",$exec,"20 60"); } elsif ($choice eq "E"){ # list groups in the domain. $ans=&list_groups("list only"); } elsif ($choice eq "B"){ # restart sendmail. my $exec=`$chroot $domain $sendmail -bi &1`; if ($?) { &error("Error!:\n$exec"); &logit("Error with Sendmail: $?") if ($log); return 1; } &logit("Sendmail alias and restart: $exec") if ($log); $ans=&text_box("Alias Database",$exec,"20 68"); } elsif ($choice eq "O"){ # add a group. my $addgroup=&findpath("addgroup"); $ans=&add_group($addgroup) if ($addgroup); } elsif ($choice eq "V"){ # Apache Configuration $ans=&apache_config(); } # return to listing the menu as we got a good response from the above functions. return 1; } sub change_passwd{ my ($text,$server,$passwd)=@_; my ($acts,$i,$j); my (@accounts)=split(/\n/,$text); for ($i=0;$i<@accounts;$i++){ $j=$i+1; $acts .= " $j \"$accounts[$i]\""; } &menu($menu_title,"\"Delete Accounts\"","20 70 11","$ansfile",$acts); my $choice=&get_answer("$ansfile"); return 1 if (!$choice); $choice--; my $exec = "$chroot $server $passwd $accounts[$choice]"; my $status=system("$exec"); print "\nPress the enter key to re-enter virtfs\n"; my $reentry=; &logit("Password for $accounts[$choice] reset") if ($log); $text = "Password for $accounts[$choice] changed.\n"; &info ($backtitle,$text,"10 50"); return 0; } sub add_group{ my ($addgroup)=@_; if (!$addgroup){&error("addgroup not found!\nYou may need to edit this script!");return;} my $text="Name of Group to add:"; my ($group)=&input($backtitle,$text,"","12 55"); return 1 if (!$group); my $exec=`$chroot $domain $addgroup $group &1`; my $log_text="Added group: $group"; $log_text .= ". Error: $?" if ($?); if ($?) { &error("Couldn't create group:\n$exec\n$!");return;} else { $text = "Group was added.\n"; &info($backtitle,$text,"12 50"); } &logit($log_text) if ($log); return 1; } sub mail_folder{ my ($text)=@_; my ($chown)=&find_path("chown"); if (!$chown){&error("chown not found!\nYou may need to edit this script!");return;} my (@accounts)=split(/\n/,$text); my ($i,$acts,$j); for ($i=0;$i<@accounts;$i++){ $j=$i+1; $acts .= " $j \"$accounts[$i]\""; } &menu($menu_title,"\"Mail Folders\"","20 70 11","$ansfile",$acts); my $choice=&get_answer("$ansfile",3); return 1 if (!$choice); $choice--; chomp ($accounts[$choice]); my $ex; if (! -d $domain.$mail_folder){ $ex = "$mail_folder was not found within domain.\n"; $ex .= "Edit $config_file. Are you running Sendmail?\n"; &text_box("Mail Folder","$ex","15 62"); return 1; } my $mailfile=$domain.$mail_folder."/".$accounts[$choice]; if (-e $mailfile){ $ex="Mail folder found:\n$mailfile ."; $ex .= "\nDelete and re-create the mail folder?"; my $del_folder=&yes_no("Mail Folder",$ex,"14 62"); if ($del_folder == 0){ unlink $mailfile; } else {return 1;} } open (FH, "+> $mailfile"); close (FH); $ex="Mail file $mailfile\ncreated."; $ex .= "\nPermissions were also passed.."; my $mailfolder=$mail_folder."/".$accounts[$choice]; chmod 0600, $mailfile || die "Couldn't change permissions of $mailfile: $!\n"; my $exec=`$chroot $domain $chown $accounts[$choice].$mail_grp $mailfolder &1`; if ($?) { print $exec; &logit("Error when creating a mail folder for $accounts[$choice]: $?") if ($log); exit(0); } &text_box("Mail Folder","$ex","15 62"); &logit("Mail folder for $accounts[$choice] created: $mailfolder") if ($log); return 1; } sub finger_account{ my ($text,$finger)=@_; my (@accounts)=split(/\n/,$text); my ($i,$acts,$j); for ($i=0;$i<@accounts;$i++){ $j=$i+1; $acts .= " $j \"$accounts[$i]\""; } &menu($menu_title,"\"Finger Account\"","20 70 11","$ansfile",$acts); my $choice=&get_answer("$ansfile",3); if (!$choice){return 1;} $choice--; chomp ($accounts[$choice]); my $ex=`$chroot $domain $finger -l $accounts[$choice] &1`; &text_box("Finger",$ex,"21 62"); return 1; } sub delete_account{ my ($text,$server,$userdel)=@_; my ($i,$acts,$j,$log_text,$log_text2,$error_text); my (@accounts)=split(/\n/,$text); for ($i=0;$i<@accounts;$i++){ $j=$i+1; $acts .= " $j \"$accounts[$i]\""; } &menu($menu_title,"\"Delete Accounts\"","20 70 11","$ansfile",$acts); my $choice=&get_answer("$ansfile",3); return 0 if (!$choice); # cancelled pressed. $choice--; if (($accounts[$choice] eq "root") && ($delete_root == 1)){ $error_text = "The root account cannot be removed!\n"; &info ($backtitle,$error_text,"10 60"); return 1; } my ($exec,$ex); my $del_text = "Delete User's Home Directory?"; my $del_home=&yes_no("Home Dir!",$del_text,"14 62"); if ($del_home == 0){ $ex="$chroot $server $userdel -r $accounts[$choice]"; $log_text2 = " Home directory was also deleted."; } else { $ex = "$chroot $server $userdel $accounts[$choice]";} my $ctext="Are you sure you would like to delete $accounts[$choice]"; $ctext .= "?" if ($del_home != 0); $ctext .= "\n"; $ctext .= "and the home dir contents?" if ($del_home == 0); my $confirm=&yes_no("Confirm",$ctext,"14 62"); if ($confirm == 0){ my $exec=`$ex &1`; $exec = "User $accounts[$choice] deleted." if (!$exec); $log_text = "$domainname: User Account $accounts[$choice] deleted."; $log_text .= $log_text2; $log_text .= " - $exec" if ($exec); &logit ($log_text) if ($log); &text_box("User Deleted",$exec,"20 60"); } return 1; } sub services{ # this function tweaks the service files, ie. conf.pop and conf.ftp. # it takes the service file and the name of the service as arguments, # ie. "conf.samba" and "SAMBA" could be an example you may want to implement # yourself. my ($file,$service)=@_; my ($active)=&conf_files($file); my ($text,$dialog,$copy); if ($active eq "Yes"){ my $text = "The $service service is currently active.\nDisable It?"; my $dialog=&yes_no("Home Dir!",$text,"14 62"); if ($dialog == 0){ &delete_conf_entry($file); } } elsif ($active ne "Yes"){ $text = "The $service service is not active.\nEnable It?"; my $dialog=&yes_no("Service",$text,"14 62"); if ($dialog == 0){ if ($service eq "FTP"){ $text = "Copy over the FTP config. files?"; my $copy=&yes_no("Files",$text,"14 62"); if ($copy == 0){ &ftp_files(); } } # end if $service eq "FTP" &edit_conf_file($file); } } my $final_active=&conf_files($file); if ($final_active eq "Yes"){ $text = "$service service is currently active";} else{ $text = "$service service is currently not active"; } &info ($backtitle,$text,"10 50"); return; } sub ftp_files(){ # copy over the ftp config files my @ftp_config_files=split(/ /,$ftp_config_files); my ($i); for ($i=0;$i<@ftp_config_files;$i++){ `cp $ftp_config_files[$i] $domain/etc`; } return; } sub su_exec{ # simly su over to the server as if you just telnetted into the virtual domain. my ($server,$su)=@_; my $text = "Su over to $server as which user?\n"; $text .= "(Virtfs will exit)"; my ($su_user)=&input($backtitle,$text,"root","12 55"); if (!$su_user){return 1;} if (!$su){&error("su not found!\nYou may need to edit this script!");return;} &logit("su to server $domainname as $su_user") if ($log); exec ("$chroot $server $su $su_user") || &error("$!"); exit(0); #in case } sub find_path{ # find the path of a given file for execution. # If the file is not found, complain to the user. my ($file)=@_; my ($text,$error_apps,$app,$i); my @paths=("/usr/sbin","/usr/bin","/usr/local/bin","/bin","/usr/lib"); for ($i=0;$i<@paths;$i++){ if (-e "$domain$paths[$i]/$file"){ $app="$paths[$i]"."/".$file; last; } } if ($app){ return $app; } else { $text .= "$file could not be found in $domain \n"; $text .= "\nCorrect this problem if you "; $text .= "wish to use \n'$file' from virtfs."; my $continue=&info($backtitle,$text,"15 62"); return 0; } return 1; } sub list_all{ open (SF, $server_file); my ($list,$d,$p); while (){ s/#.*//; s/^\s+//; s/\s+$//; ($d,$ip)=split(/\:/,$_); $list .= "$d - $ip\n" unless (!$d); } my $continue=&info($backtitle,$list,"15 50"); return 1; } sub check_username{ # confirm if the username is a legal one. my ($user)=&input($backtitle,"Please Enter a Username","","12 55"); if (!$user){return 0;} if ($user !~ /^[a-z0-9_][a-z0-9_\-]*$/ || $user eq "a-z0-9_-") { # if this is an illegal username... my $badname= "Please use only lowercase characters or digits\n"; &text_box("Illegal Name","$badname","15 62"); return 0; } return $user; } sub add_user{ # Add a user to a domain. Similar to how virtexec would carry this out. # It will ask for the username, the name of the account and the home directory. my ($server,$adduser)=@_; my $text = "Please enter the username:\n"; my $log_text; my $user; while (1){ # check with input if username is correct, if it isn't display message and ask for input again. ($user)=&check_username; last if ($user); last if (!$user); } return 1 if (!$user); # user cancelled $text = "What is the full name of $user\n"; my ($name)=&input($backtitle,$text,"","12 55"); $text = "Default group for $user:\n"; my $group=&list_groups("useradd"); if (!$group){return 1;} $text = "Home directory for $user (within $domainname):\n"; my ($dir)=&input($backtitle,$text,"$default_home/$user","12 55"); #$dir="$default_home/$user" if (!$dir); return 1 if (!$dir); my $shell=&list_shells(); return 1 if (!$shell); #execute the command to su over as a user using '/' as the virtual directory. my $exec; if ($name){ $exec="$chroot $server $adduser -c \"$name\" -g $group -d $dir -s $shell $user"; } else{ $exec="$chroot $server $adduser -d $dir -g $group -s $shell $user"; } if ($group eq "NO GROUP"){ $exec =~ s/-g $group//; } # if no group is defined remove the entry from the command my $status=system("$exec 2>$tmp/user"); #execute the command. my $message; # in case of any errors if ($status != 0){ open (TEMP, "+< $tmp/user"); &logit("Error occured when creating $user") if ($log); while (){ $message .= $_; # display the error to the end user, if any.. &logit("$_") if ($log); } close (TEMP); unlink ("$tmp/user"); if ($message){ &error("$message\n"); return; } } &logit("Account for $user (Name: $name) added") if ($log); my $chown=&find_path("chown"); if (! -d $domain.$dir){ #just in case... mkdir($domain.$dir, 0700) || die "couldn't create $domain.$dir - user was still created..\n: $!"; if ($chown){ if ($group){ $exec=`$chroot $domain $chown $user.$group $dir &1`; } else {$exec=`$chroot $domain $chown $user.$user $dir &1`;} if ($?) { &text_box("Mail Folder","Couldn't chown directory:\n$exec","15 62");&logit("Error when creating $dir: $?") if ($log);} } } &logit ("Home directory for $user: $dir created") if ($log); $text = "$user has been added to $domainname\n"; $text .= "Full Name: $name\n" if ($name); $text .= "Group: $group\n"; $text .= "Shell: $shell\n"; $text .= "Home Dir: $dir\n\n"; $text .= "Configure password for $user?\n"; $text .= "You can do this later from the menu\n"; my $continue=&yes_no("Password?",$text,"18 53"); if ($continue == 0){ my $passwd = &find_path("passwd"); if ($passwd){ system("$chroot $domain $passwd $user"); &logit ("Password for $user reset") if ($log); } } my ($ex); if ($smail){ # sendmail operations if ((! -d $mail_folder."/".$user) || (!$chown)){ $text = "Create a mail folder for $user in:\n $mail_folder?\nYou can do this later from the menu"; my $continue=&yes_no("Mail Folder?",$text,"12 53"); if ($continue == 0){ if (! -d $domain.$mail_folder){ # couldn't find the mail folder directory! $ex = "$mail_folder was not found within domain.\n"; $ex .= "Edit $config_file. Are you running Sendmail?\n"; &text_box("Mail Folder","$ex","15 62"); return 1; } my $mailfile=$domain.$mail_folder."/".$user; open (FH, "+> $mailfile") || die "Didn't work - fix virt.conf for mail dir.- user still created: $!\n"; close (FH); $ex="Mail file $mailfile\ncreated."; $ex .= "\nPermissions were also passed.."; &logit ("Mail folder for $user was created.") if ($log); my $mailfolder=$mail_folder."/".$user; chmod 0600, $mailfile || &text_box("Mail","Couldn't change permissions of $mailfile: $!\n","15 62"); my $exec=`$chroot $domain $chown $user:$mail_grp $mailfolder &1`; # if an error was found if ($?) { print $exec; &logit($?) if ($log); exit(0); } &text_box("Mail Folder","$ex","15 62"); } # end continue } } #end if smail return 1; } sub apache_config{ my $intro = "The next few questions will help you in setting up your "; $intro .= "virtual host for web services, through Apache."; $intro .= "After this is done, it is up to you to add more features "; $intro .= "that you may want manually, and restart Apache..."; my $continue=&info($backtitle,$intro,"15 50"); my $text = "Where is Apache's httpd.conf file?"; my ($conf)=&input($backtitle,$text,"$apache_conf","15 55"); return 1 if (!$conf); if (! -e $conf){ $text = "Could not find or edit:\n $conf!\n"; $text .= "Edit $config_file\n"; &text_box("Missing Apache File",$text,"10 62"); return 1; } my ($dom,$confirm,$virthost,$final,$sname); while (1){ $text = "Enter the domain name for which you would like to configure: "; $text .= " ie. www.$domainname "; $dom =&input($backtitle,$text,"www.$domainname","15 55"); return 1 if (!$dom); $virthost = "\n"; $text = "Server Name? ie. $domainname"; $sname=&input($backtitle,$text,$domainname,"15 55"); return 1 if (!$sname); $virthost .= "ServerName $sname\n"; $confirm = &apache_confirm($virthost); last if ($confirm); } $final .= $virthost; my ($adminemail,$errorlog,$tlog,$alog,$rootdir,$cgi); while (1){ $text = "Enter in the Virtual Host Admin E-Mail Address:"; $adminemail=&input($backtitle,$text,"","15 55"); return 1 if (!$adminemail); $text = "The Virtual Host Document Root is where the web site content"; $text .= " will be stored."; $text .= " Please enter the full path for where this will be located:"; $rootdir=&input ($backtitle,$text,"","16 55"); return 1 if (!$rootdir); $virthost = $final; $virthost .= "ServerAdmin $adminemail\n"; $virthost .= "DocumentRoot $rootdir\n"; $confirm = &apache_confirm($virthost); last if ($confirm); } $final = $virthost; while (1){ $text = "Please enter in a full path filename for the error log. "; $text .= "Type 'none' if you don't want this feature."; $errorlog=&input($backtitle,$text,"","15 55"); return 1 if (!$errorlog); $virthost = $final; $virthost .= "ErrorLog $errorlog\n" if ($errorlog ne "none"); $text = "Please enter in a full path filename for the transfer log. "; $text .= "Type 'none' if you don't want this feature."; $tlog=&input($backtitle,$text,"","15 55"); return 1 if (!$tlog); $virthost .= "TransferLog $tlog\n" if ($tlog ne "none"); $confirm = &apache_confirm($virthost); last if ($confirm); } $final = $virthost; while (1){ $text = "If you want CGI enabled, please enter the location of the "; $text .= "cgi-bin directory. The alias will also be created. "; $text .= "Enter 'none' if you do not want this feature."; $cgi=&input($backtitle,$text,"","15 55"); return 1 if (!$cgi); $virthost = $final; $virthost .= "ScriptAlias /cgi-bin/ $cgi\n" if ($cgi ne "none"); $virthost .= "AddHandler cgi-script .cgi .pl\n" if ($cgi ne "none"); $confirm=&apache_confirm($virthost); last if ($confirm); } $final = $virthost; #open (CONF, "+< $conf"); #close (CONF); $final .= "\n"; my $added=0; # generate backups for httpd.conf operations.. my $new=$conf . ".new"; my $old=$conf . "-pre-".$domainname; link ($conf,$old); # backups open (NEW, ">$new"); open(CURRENT, "+< $conf"); while (){ print NEW $_; if ((/\<\/VirtualHost\>$/) && ($added == 0)) { $added = 1; print NEW "\n\n"; print NEW $final; } } close (CURRENT); if ($added == 0){ print NEW $final; } close (NEW); unlink ($conf); rename($new,$conf); $text = "Changes have been made to:\n $conf.\n\n"; $text .= "A backup was saved as:\n$old\n"; &text_box("Edits Done!",$text,"15 60"); &logit("Apache configuration set:\n $final") if ($log); return 1; } sub apache_confirm{ my ($virthost)=@_; my ($confirm,$continue); $confirm = "This is the configuration so far:\n"; $confirm .= $virthost; $confirm .= "\n\n"; $confirm .= "Is this correct?"; $continue=&yes_no("Confirm",$confirm,"20 53"); if ($continue == 0){ return 1; } return 0; } sub list_shells{ if (! -e $shell_file){return 0;} open(S, $shell_file) || die "$shell_file:$!\n"; my (@shells,$sh,$i,$j); push (@shells,"/bin/false"); while() { if (/^\s*\//) { s/^\s*//; s/\s+.*//; # chop $sh = $_; if (-x $domain."/".$sh) { push (@shells,$sh); } } } close (S); my $shells; for ($i=0;$i<@shells;$i++){ $j=$i+1; $shells .= " $j \"$shells[$i]\""; } &menu($menu_title,"\"Choose a Shell\"","20 70 12","$ansfile",$shells); my $choice=&get_answer("$ansfile",3); if ((!$choice)||($choice == 0)){return 0;} $choice--; return $shells[$choice]; } sub list_groups{ # open /etc/group within the virtual directory and read in the group information. my ($method)=@_; my $group_file=$domain."/etc/group"; if (! -e $group_file){return 0;} my $LOCK_SH=1; my $LOCK_EX=2; my $LOCK_NB=4; my $LOCK_UN=8; my ($group,$i,$passwd,$gid,@group,%gid,$users,%users,%group,$grps,$j); open (GROUP, "$group_file") || die "Error: can't open $group_file\n"; flock(GROUP, $LOCK_EX | $LOCK_NB) || die "The password file is currently busy: $!\n"; while () { chop; ($group,$passwd,$gid,$users) = split(/:/); $group{$group}=$group; $gid{$group}=$gid; $users{$group}=$users; } flock(GROUP, $LOCK_UN); close(GROUP); if ($method eq "useradd"){ $group{"NO GROUP"}="NO GROUP"; @group=sort keys (%group); for ($i=0;$i<@group;$i++){ $j=$i+1; $grps .= " $j \"$group[$i] : $gid{$group[$i]}\""; } &menu($menu_title,"Groups","20 70 12","$ansfile",$grps); my $choice=&get_answer("$ansfile",3); if ((!$choice)||($choice == 0)){return 0;} $choice--; return $group[$choice]; } else { @group=sort keys (%group); for $i (@group){ $grps .= "$i : $gid{$i} : $users{$i}\n"; } &text_box("Groups List",$grps,"20 60"); return 1; } } # end list_groups sub list_accounts{ # list all the user accounts in an alpahabetical order. my ($server)=@_; my ($login,$uid,$pwgid,$gecos,$home_dir,$shell)= &readpasswd(); #read in all usernames my ($name,$text,$i); my @tmp = sort keys(%$login); for $i (@tmp){ $text .= "$i\n"; } return $text; } sub list_users{ # Simply parse the passwd file of the domain and send it off to the # text file viewer. Display the Username, their home directory and the shell. my ($server)=@_; my ($login,$uid,$pwgid,$gecos,$home_dir,$shell)= &readpasswd(); my @tmp=sort keys(%$login); my $i; my $text = "Account Dir Shell\n"; $text .="----------------------------\n"; for $i (@tmp){ $text .= "$i - "; $text .= "$home_dir->{$i} - " if ($home_dir->{$i}); $text .= "[none] - " if (!$home_dir->{$i}); $text .= "$shell->{$i} " if ($shell->{$i}); $text .= "[none]" if (!$shell->{$i}); $text .= "\n"; } return $text; } sub root_check{ my ($test); die "You are not root - you need to have root access to run virtfs .\n" if $< && !$test; return; } sub list_domains{ my ($virtual)=@_; # List all domains. We first check the virtfs configuration files, and # then the leading virtual directory for (unlisted) domains. #automatically add virtual domains to $server_file with $domain/etc entries my (@dirs,$name,$i,@domains,$list,$ip,@list,@sorted_list); if (-e $server_file){ open (FH,"+< $server_file"); while (){ chomp; s/#.*//; s/^\s+//; s/\s+$//; next unless length; ($name,$ip)=split(/\:/, $_,2); $i++; $list .= "$name $ip " if $name && $ip && (-d "$virtual_dir/$name/etc"); # look for a filesystem #push (@list, "$name $ip ") if $name && $ip && (-d "$virtual_dir/$name/etc"); # look for a filesystem } close (FH); } else{ open (FH, ">> $server_file"); print FH "# Created by virtfs - please don't edit this unless you know what you're doing\n"; close (FH); } $list .= " Create Server"; # add directories! &menu($menu_title,"Domains","20 70 12","$tmp/domain",$list); my $choice=&get_answer("$tmp/domain"); # ,1 if (!$choice){print "\n";exit(0);} open (FH,"+< $server_file") || die "Cannot open $server_file. Please make sure the configuration is alright: $!\n"; my $found; if ($choice ne "Create"){ # user is editing an existing virtual domain. # find out what the user inputted and send the domainname and IP address back. while (){ next unless length; ($name,$ip)=split(/\s*\:\s*/,$_,2); if ($name eq $choice){ $found=1; } } } close (FH); return ($choice,$ip) if ($found); return ($choice); } sub radiolist{ # Give the end user a choice of radio buttons. my ($title,$subtitle,$size,$menu_file,$list)=@_; system ($dialog . " --clear --title $title --radiolist $subtitle $size $list 2> $menu_file"); return; } sub text_box{ # Display the text file viewer of a certain file. my ($title,$text,$size)=@_; open (TEMP, ">$tmp/text"); print TEMP $text; close (TEMP); system ($dialog ." --clear --title \"$title\" --textbox $tmp/text $size"); unlink "$tmp/text"; return 1; } sub error{ # Generic error message. Here the user is given two choices. To return to the menu or # exit once and for all. my ($message)=@_; chomp ($message); my $text .= "Error Found:\n$message\n"; &logit("Caught Error: $message\n") if ($log); $text .= "Continue?\n"; my $continue=&yes_no("Error!",$text,"12 53"); if ($continue==0){ return; } else{ exit(0); } } sub list_menu{ # List the menu to the user and return the user's choice back to the main # part of the script. # print the sendmail menu options IF and only IF sendmail is configured in /etc/virt.conf my ($domain)=@_; my $list = "I \"Server Information\""; $list .= " C \"Change Name or IP\""; $list .= " R \"Delete Server\""; $list .= " V \"Configure Apache\""; $list .= " S \"su to Server\""; $list .= " F \"FTP Service\""; $list .= " M \"Mail Service\""; $list .= " A \"Add Account\""; $list .= " D \"Delete Account\""; $list .= " G \"Finger/Confirm Account\""; $list .= " P \"Change Password\""; $list .= " U \"List Users\""; $list .= " E \"List Groups\""; $list .= " O \"Create Group\""; $list .= " T \"Create Mail Folder\"" if ($smail); $list .= " Q \"View Sendmail Mail Queue\"" if ($smail); $list .= " B \"Rebuild Sendmail Aliases\"" if ($smail); $list .= " L \"List All Virtual Domains\""; $list .= " H \"Help\""; $list .= " W \"About\""; &menu($menu_title,"\"Menu For $domainname\"","20 50 11","$ansfile",$list); return; } sub menu{ my ($title,$subtitle,$size,$menu_file,$list)=@_; system ($dialog . " --clear --title $title --menu $subtitle $size $list 2> $menu_file"); return; } sub yes_no{ my ($title,$text,$size)=@_; if (!$size){ $size = "8 35"; } my $status=system ($dialog ." --backtitle \"Virtual Services - virtfs\" --clear --yesno \"$text\" $size 2> $ansfile"); # 0 is returned if 'Yes' was chosen. return $status; } sub parse_args{ # parse the arguments... my (@argv)=@_; while ($_ = $argv[0]) { shift @argv; if (/^-detect$/){&detect_new(); exit(0);} else { &usage($_);exit(0);} } return; } sub usage{ #user entered in an invalid argument to virtfs. # output the proper arguments and exit. my ($arg)=@_; warn < $ansfile"); if (($exec != 0) && ($ex)){ # user hit 'Cancel' so let's exit.... print "Exiting...\nThank you for using virtfs.\n"; exit(0); } if ($exec != 0){ #when cancel is pressed and we do not want to exit the program, as we do above. return 0; } my ($choice)=&get_answer("",$ex); return $choice; } sub delete_conf_entry{ my ($conf)=@_; chomp($ip); chomp($domain); open (CONF, "+< $conf"); open (TEMP, "+> $tmp/conf"); my $format="$ip $domain"; while (){ print TEMP $_ unless $_ =~ /$format/; } close (CONF); close (TEMP); system ("mv $tmp/conf $conf"); &logit("Server entry in $conf (service file) was removed") if ($log); return; } sub edit_conf_file{ # change the service file, ie. conf.pop or conf.ftp adding the specified virtual server # information. my ($conf)=@_; chomp($ip); chomp($domain); my ($found,$temp,$format); if (!-e $conf){ open (CONF, ">> $conf") || die "Couldn't create $conf\n"; print CONF "# Automatically written by Virtfs.\n"; print CONF "# Please don't edit this unless you know how to.\n"; print CONF "# ie. IP space DIRECTORY\n\n"; print CONF "$ip $domain\n"; print CONF "\ndefault /\n"; close (CONF); } else { open (CONF, "+< $conf"); unlink "$tmp/conf" if (-e "$tmp/conf"); $temp="$tmp/conf"; $format="$ip $domain"; open (TEMP, ">> $temp") || die "Couldn't open $temp!\n"; while (){ if (($_ =~ /default \//) || ($_ =~ /$format/)){$found=1;} else{ print TEMP $_ unless ($_ =~ /^$/); # strip the blank lines. } } close (CONF); print TEMP "$format\n" if ($found); print TEMP "\ndefault /\n"; # we must always keep default / as the last line! close (TEMP); &logit("Entry for server was added to $conf (service file)") if ($log); system ("mv $temp $conf"); } return; } sub check_ip_format{ my ($ipaddr)=@_; # check ip format is in x.x.x.x format, otherwise return false. if (!$ipaddr){return 255;} return 1 if ($ipaddr =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ && $1 >= 0 && $1 <= 255 && $2 >= 0 && $2 <= 255 && $3 >= 0 && $3 <= 255 && $4 >= 0 && $4 <= 255); return 0; } sub remove_server_entry{ #delete the virtual domain and ip entries in the servers.list file. my ($domainname)=@_; chomp ($ip); my $list_format=$domainname.":".$ip; open (SR, "+< $server_file"); open (TEMP, "+>>$tmp/domain.tmp"); while (){ chomp; print TEMP "$_\n" unless $_ =~ /^$domainname/; } close (TEMP); close (SR); system ("mv $tmp/domain.tmp $server_file"); #lazy method &logit("Information for this server was removed from $server_file") if ($log); return; } sub get_answer{ # This functions gets the user input from the dialog boxes. my ($file,$ex)=@_; if (!$file){$file = "$ansfile";} my ($choice); open (ANSWER, "$file"); while (){ chomp; $choice=$_; } close (ANSWER); unlink ($ansfile); if ((!$choice) && ($ex == 3)){ return; } elsif ((!$choice) && ($ex == 1)){ return 0; #exit } elsif (!$choice){ return 0; } return $choice; } sub write_up{ # This function writes in the domain-specific configuration stuff into a temp file. my ($key,$value)=@_; open (TEMP, "+>> $tmp/choices"); print TEMP "$key:$value\n"; close (TEMP); return; } sub info{ # this function simply builds the Info box from Dialog. my ($title,$text,$size)=@_; if (!$size){ $size="22 53"; } system($dialog . " $title --msgbox \"$text\" $size"); return 1; } sub logit{ # log the procedures carried out if log was set. my ($log_message)=@_; my @make_date_month = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); my @gmt = gmtime(time()); my @lct = localtime(time()); my $days = $lct[3] - $gmt[3]; my $hours = ($days < -1 ? 24 : 1 < $days ? -24 : $days * 24) + $lct[2] - $gmt[2]; my $mins = $hours * 60 + $lct[1] - $gmt[1]; my $timezone = ($mins < 0 ? "-" : "+"); $mins = abs($mins); $timezone .= sprintf "%2.2d%2.2d", $mins/60, $mins%60; # end my (@tm, $dstr, $addr, $user, $ident); @tm = localtime(time()); $dstr = sprintf "%2.2d/%s/%4.4d - %2.2d:%2.2d:%2.2d %s", $tm[3], $make_date_month[$tm[4]], $tm[5]+1900, $tm[2], $tm[1], $tm[0], $timezone; open (LOG, ">>$logfile") || die "Couldn't open $logfile for logging. Check configuration"; if ($log_message eq "clear"){ print LOG "\n"; } else{ print LOG "[$dstr] $domainname: $log_message\n"; } close (LOG); return; } sub create_virt_domain{ # main function for creating a virtual directory. unlink ("$tmp/choices"); my $domain=&get_virtual_dir; # specify all the directories needed &get_virtual_ip($domain); # And the IP address needed &write_up("copyfile",$copy_file); my ($config)=&config_lookup; # Summarise what is going on to the user: my $text .= "This is the current configuration\n\n"; $text .= "V. Server Directory: $config->{'virtdir'}\n"; $text .= "Server Name: $config->{'domain'}\n"; $text .= "Server IP Address: $config->{'virtip'}\n"; $text .= "\nConfiguration File: $config->{'copyfile'}\n"; $text .= "\nProceed?\n"; my ($status)=&yes_no($backtitle,$text,"18 53"); if ($status != 0){ # user did not like what (s)he saw...leave... print "User did not like the configuration..Exiting...\n"; exit(0); } &execute($config); # Configuration is set, carry out operations &create_virtual_server($config); # copy all the files as read in. return; } sub create_virtual_server{ my ($config)=@_; my ($copy_files)=$config->{'copyfile'}; my $domain=$config->{'domain'}; my $text = "The files are about to be hard linked from:\n $template_dir.\n"; $text .= "A log will be kept in $tmp/$config->{'domain'}.\n\n"; $text .= "Please view that once the linking is done.\n"; $text .= "\nProceeding will start the linking process...\n"; &info($backtitle,$text,"15 55"); my (@ex,$i); open (FH, "+< $copy_files"); unlink ("$tmp/$config->{'domain'}"); my ($system,$execute); # Hard link ALL the files in the template directory to the files in the new virtual server. system ("cp -alv $template_dir/* $config->{'virtdir'} >>$tmp/$config->{'domain'} 2>&1"); # Copy over the custom commands defined in /etc/virt.conf under the &execute_custom_commands($config_file,$config->{'virtdir'},$config->{'domain'}); &write_hosts_file($config->{'virtdir'},$config->{'domain'},$config->{'virtip'}); &create_virtual_directories($config->{'virtdir'}); close (FH); if (!-e "$config->{'mainvirtdir'}/servers.lists"){ open (RD, ">>$config->{'mainvirtdir'}/servers.lists"); print RD "# DO NOT TOUCH THIS FILE\n"; print RD "$config->{'domain'}:$config->{'virtip'}\n"; } else { open (RD, ">>$config->{'mainvirtdir'}/servers.lists"); print RD "$config->{'domain'}:$config->{'virtip'}\n"; } close (RD); &sendmail_config($config->{'domain'},$config->{'virtdir'}) if ($smail == 1); # configure sendmail &create_ldconfig_conf($config->{'virtdir'}); &create_resolv_conf($config->{'domain'},$config->{'virtdir'}); $text = "Congratulations!\n"; $text .= "$config->{'domain'} has been setup.\n"; $text .= "\n\nThe administrator for the server\n will be 'admin'."; &info($backtitle,$text,"15 50"); &set_admin_rights($config->{'virtdir'}); return; } sub create_virtual_directories{ # create new directories within the virtual server. # These directories should not be hard linked as they are virtual server # specific. my ($virtdir)=@_; my ($x,$y,$minor); my @prefix1 = ("p".."z", "a".."e"); my @prefix2 = (0..9, "a".."f"); for ($x = 0; $x <= 15; $x++) { for ($y = 0; $y <= 15; $y++) { $minor = ($x * 16) + $y; `mknod -m 0620 $virtdir/dev/pty$prefix1[$x]$prefix2[$y] c 2 $minor`; `mknod -m 0620 $virtdir/dev/tty$prefix1[$x]$prefix2[$y] c 3 $minor`; } } # end for `mknod -m 0666 $virtdir/dev/random c 1 8`; `mknod -m 0666 $virtdir /dev/null c 1 5`; `mknod -m 0666 $virtdir/dev/urandom c 1 9`; `mknod -m 0666 $virtdir/dev/tty c 5 0`; # Create usr/local stuff } sub sendmail_config{ # Configure Sendmail. # Copy, and edit files: sendmail.cw, sendmail.cf, /etc/mail/* and aliases my ($domain,$virtdir)=@_; my @sendmail_domains=("localhost","$domain","mail.$domain"); my $text = "You have set Virtfs up for Sendmail configuration.\n"; $text .= "Should we configure $domain for Sendmail?\n"; my ($status)=&yes_no($backtitle,$text,"15 58"); if ($status != 0){ # user chose no return; } else{ my $i; # counter open (CW, "+>>$virtdir/etc/sendmail.cw"); print CW "# sendmail.cw - aliases for your virtual server here\n"; for ($i=0;$i<@sendmail_domains;$i++){ print CW $sendmail_domains[$i]."\n"; } close (CW); `cp -fp $sendmail_cf $virtdir/etc/`; `cp -fp $sendmail_alias $virtdir/etc/`; `cp -a /etc/mail $virtdir/etc`; &alter_sendmail_cf($domain,$virtdir); mkdir ("$virtdir/var/spool/mqueue",0755); $text = "$virtdir/etc/sendmail.cw configured...\n"; $text .= "$virtdir/etc/sendmail.cf configured...\n"; $text .= "$virtdir/var/spool/mqueue created...\n"; $text .= "$virtdir/etc/aliases copied...\n"; $text .= "$virtdir/etc/mail copied...\n"; &info($backtitle,$text,"13 50"); } return; } sub set_admin_rights{ my ($virtdir)=@_; my $admin_list = &read_admin_config($config_file); chroot ($virtdir); chdir("/"); # Create the admin user and group my $adduser=&find_path("adduser"); my $groupadd = &find_path("groupadd"); my $chown = &find_path("chown"); `$groupadd admin`; my ($admin_info,$gid,$users)=&get_gid("/etc/group"); my $admin_gid = $gid->{'admin'}; my $admin_uid = $admin_gid; `$adduser -c \"Administrator\" -d /root -u $admin_uid -g admin -n -s /bin/bash admin`; # Give ownership of /usr/local to the admin my @new_directories=("/usr/local","/usr/local/etc","/usr/local/include","/usr/local/src", "/usr/local/man","/usr/local/bin","/usr/local/sbin","/usr/local/lib"); foreach (@new_directories){ mkdir ($_, 0755); chown $admin_uid, $admin_gid, $_; } my @admin_dirs = split(/ /, $admin_list->{"Admin Directories"}); my @admin_files = split (/ /, $admin_list->{"Admin Files"}); foreach (@admin_files){ if (!-d $_){ chown $admin_uid, $admin_gid, $_; } } foreach (@admin_dirs){ if ($_ =~ /\*$/){ my ($chown_dir,$tmp)=split(/\*$/,$_); `$chown -R $admin_uid.$admin_gid $chown_dir`; } else{ if (!-d $_){mkdir ($_, 0755);} chown $admin_uid, $admin_gid, $_; } } return; } sub alter_sendmail_cf(){ my ($domain,$virtdir)=@_; my $cf=$virtdir."/etc/sendmail.cf"; open (TMP, "+>>$tmp/$domain.cf"); open (CF, $cf); print TMP "### This sendmail.cf file has been generated for $domain by Virtfs.\n\n"; while (){ if ($_ =~ /Dj/){ # replace the Dj setting to tell sendmail which domain it is print TMP "\n# This is how we tell Sendmail which domain this is - edited by Virtfs.\n"; print TMP "Dj$domain\n\n"; } print TMP $_; } close (TMP); close (CF); rename ("$tmp/$domain.cf",$cf); chmod (0644,$cf); return; } sub check_sendmail_config{ my ($sendmailcf)=@_; if (!-e $sendmailcf){ print "I could not find $sendmailcf even though you have specified that Virtfs should use Sendmail.\n"; print "Please edit $config_file and alter the Sendmail section.\n"; exit; } return; } sub create_ldconfig_conf{ # create a default conf file for ldconfig my ($virtdir)=@_; my $i; my @ld_dirs=split (/ /, $ldconfig_libs); open (LDCONF, "+>>$virtdir/etc/ld.so.conf"); for ($i=0;$i<@ld_dirs;$i++){ print LDCONF $ld_dirs[$i]."\n"; } close (LDCONF); return; } sub create_resolv_conf{ my ($domain,$virtdir)=@_; open (RESOLV, "+>>$virtdir/etc/resolv.conf"); print RESOLV "domain ".$domain."\n"; print RESOLV "nameserver ". $ns1."\n"; print RESOLV "nameserver ". $ns2."\n"; close (RESOLV); return; } sub execute{ #carry out the directory creation and pass on the variables my ($config)=@_; if (!-d $config->{'mainvirtdir'}){ mkdir $config->{'mainvirtdir'},0755 || die "Couldn't create directory!"; } mkdir $config->{'virtdir'},0755 || die "Couldn't create directory!"; } sub get_virtual_dir{ if (!-d $virtual_dir){ my $warningtext="The virtual directory $virtual_dir does not exist. Please enter in a default directory"; $warningtext .= " which will be created for you."; ($virtual_dir)=&input($backtitle,$warningtext,"$virtual_dir","15 55"); } my ($domain)=&input($backtitle,"Please Enter Domain Name (domain.com)","","15 55",1); if (-d "$virtual_dir/$domain"){ print "$domain seems to already exist! Try removing the server before trying to set it up again!\n"; exit(0); } if (!$domain){exit (0);} &write_up("domain",$domain); &write_up("virtdir","$virtual_dir/$domain"); &write_up("mainvirtdir",$virtual_dir); return $domain; } sub get_virtual_ip{ my ($domain)=@_; my ($ip,$stat); while (1){ ($ip)=&input($backtitle,"Please enter the IP address for $domain","","15 55"); $stat=&check_ip_format($ip); exit(0) if ($stat == 255); last if ($stat); } &write_up("virtip",$ip); # send to write it into the configuration file. return; } sub execute_custom_commands{ my ($file,$virtual,$domain)=@_; open (FH, "+< $file"); $virtual =~ s:/$::; my ($name,$value,%config); while (){ chomp; s/#.*//; s/^\s+//; s/\s+$//; next unless length; if (/^/){ while (){ chomp; s/#.*//; s/^\s+//; s/\s+$//; next unless length; last if (/^<\/Shell Commands>/); s/!!virtual/$virtual/g; s/!!domain/$domain/g; system ("echo $_ >>$tmp/$domain"); system ("$_ 2>>$tmp/$domain"); } } } close (FH); return; } sub write_hosts_file{ my ($virtdir,$domain,$ip)=@_; # Writes the /etc/hosts file within the virtual server open (HOSTS, ">$virtdir/etc/hosts"); print HOSTS $ip."\t" . $domain ."\t localhost"; close (HOSTS); return; } sub read_template_config{ my ($template_conf)=@_; # read the template conf file.. my ($template_dir,$name,$value); open (TEMPLATE, $template_conf); while (