#!/usr/bin/ruby # -*- encoding: binary -*- unless RUBY_VERSION >= "1.9.2" raise ::LoadError, "OverSIP requires Ruby version >= 1.9.2 (current version is #{RUBY_VERSION})" end $LOAD_PATH.insert 0, File.expand_path(File.join(File.dirname(__FILE__), "../", "lib")) # When OverSIP is executed automaticaly via the system init (i.e. after booting the host) # the Encoding.default_external is US_ASCII which causes fails when reading daat from # some files (i.e. the cacert.pem file which contains no valid US_ASCII symbols). So # make the default external encoding UTF-8 right now. ::Encoding.default_external = ::Encoding::UTF_8 # First of all, trap some signals in order to ignore them if they arrive while # loading server libraries. [:HUP, :INT, :USR1, :USR2].each {|signal| trap(signal) {} } require "optparse" require "etc" require "oversip" module OverSIP class Executable extend ::OverSIP::Logger @log_id = "executable" def self.run $0 = ::File.basename(__FILE__) ::OverSIP::Logger.load_methods # Options by default. options = { :colorize => true } OptionParser.new("", 28, " ") do |opts| opts.banner = "#{::OverSIP::DESCRIPTION}" \ "\n\nUsage: #{File.basename(__FILE__)} " \ "[#{::OverSIP::PROGRAM_NAME} options] [Ruby options]" opts.separator "\n#{::OverSIP::PROGRAM_NAME} options:" opts.on("-P", "--pid FILE", "Create a PID file (required)") do |value| options[:pid_file] = value end opts.on("-p", "--process-name NAME", "Change the running process name, also affects to syslogger process and Posix Message Queue name (default 'oversip')") do |value| options[:process_name] = value $0 = options[:process_name] ::OverSIP::Logger.load_methods end opts.on("--config-dir DIR", "Absolute path to the directory with user configuration files (default '/etc/oversip/')") do |value| options[:config_dir] = value end opts.on("--config-file FILE", "Name of the configuration file within the configuration directory (default 'oversip.conf')") do |value| options[:config_file] = value end opts.on("-u", "--user USER", "System user to run with") do |value| options[:user] = value end opts.on("-g", "--group GROUP", "System group to run with") do |value| options[:group] = value end opts.on("--no-color", "Don't colorize text printed in stdout") do |value| options[:colorize] = false end opts.on("--remove-mqueue MQUEUE", "Destroy the Posix Message Queue with the given name and exit") do |value| require "posix_mq" begin ::POSIX_MQ.unlink value rescue ::Errno::ENOENT rescue ::Errno::EACCES => e fatal "cannot remove '#{value}' posix message queue due file permissions" exit 1 rescue ::Errno::EINVAL => e fatal "cannot remove '#{value}' posix message queue, invalid name" exit 1 ensure exit end end opts.separator "\nRuby options:" opts.on("-d", "--debug", "Set debugging flags ($DEBUG = true)") do $DEBUG = true end opts.on("-w", "--warn", "Turn warnings on ($-w = true)") do $-w = true end opts.on("-I", "--include PATH", "Add PATH to $LOAD_PATH (may be used more than once)") do |path| $LOAD_PATH.unshift(*path.split(/:/)) end opts.on("-r", "--require LIBRARY", "Load LIBRARY before running the programm (may be used more than once)") do |library| require library end opts.separator "\nCommon options:" opts.on_tail("-h", "--help", "Show this message") do puts opts.to_s exit end opts.on_tail("-v", "--version", "Show version") do puts ::OverSIP::DESCRIPTION exit end begin opts.parse! ARGV rescue ::OptionParser::InvalidOption => e log_system_error e.message puts puts opts.to_s exit! 1 rescue ::OptionParser::MissingArgument => e log_system_error e.message puts puts opts.to_s exit! 1 end end log_system_notice "#{::OverSIP::PROGRAM_NAME} #{::OverSIP::VERSION} starting..." # Options checks. # PID file is required. unless options[:pid_file] fatal "PID file is required (use -P or --pid option)" end # Ignore user/group if the launcher is not being running as root. unless ::Process.euid == 0 log_system_warn "ignoring user/group parameters when not running as root" options.delete :user options.delete :group else # Get the uid and gid to run with. if options[:user] begin ::Etc.getpwnam options[:user] rescue ::ArgumentError fatal "user '#{options[:user]}' does not exist in the system" end end if options[:group] begin ::Etc.getgrnam options[:group] rescue ::ArgumentError fatal "group '#{options[:group]}' does not exist in the system" end end end # Set the command name (as it appears in "ps" output) to given --process_name option (-p) # or to the script filename otherwise. ::OverSIP.master_name = options[:process_name] || ::File.basename(__FILE__) $0 = ::OverSIP.master_name log_system_info "master process name: #{::OverSIP.master_name}" ::OverSIP::Config.load options[:config_dir], options[:config_file] ::OverSIP::Config.print options[:colorize] log_system_info "creating Posix Message Queue for communicating master and syslogger processes" ::OverSIP.syslogger_mq_name = "/#{OverSIP.master_name}_syslogger" ::OverSIP::Logger.init_logger_mq options[:group] ::OverSIP::Logger.load_methods ::OverSIP::Launcher.daemonize!(options) ::OverSIP::Launcher.run(options) end # def run end # class Executable end # module OverSIP ::OverSIP::Executable.run