#!/usr/bin/python
#
# Copyright 2006 Soeren Boll Overgaard <boll@fork.dk>
#
# This file is part of mlmmjadmd.
#
# mlmmjadmd 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.
#
# mlmmjadmd is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with mlmmjadmd; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os;
import time;
import string;
import logging;
import optparse;
import signal;
import sys;
import mlmmjadm.conf;
from mlmmjadm.auth import *;
from mlmmjadm.server import *;
from mlmmjadm.signals import *;
import mlmmjadm.util;

configuration = mlmmjadm.conf.Configuration();

p = optparse.OptionParser();
p.add_option("-d", 
             "--debug", 
             action="store_true", 
             dest="mlmmjAdmDebug",
             help="Enable debugging output");
p.add_option("-a", 
             "--listen-address", 
             dest="mlmmjAdmBindAddress",
             help="Set the IP address to listen to");
p.add_option("-p", 
             "--listen-port", 
             dest="mlmmjAdmBindPort",
             help="Set the TCP port number to listen to");
p.add_option("-u", 
             "--users-file", 
             dest="mlmmjAdmUsers",
             help="Specify the path to mlmmjadms users file");
p.add_option("-l",
            "--log-file",
            dest="mlmmjAdmLogFile",
            help="Log to the file provided, instead of stdout");
p.add_option("-m",
             "--mlmmj-bin-prefix",
             dest="mlmmjBinPrefix",
             help="Directory containing the mlmmj binaries");
p.add_option("-r",
             "--mlmmj-list-base",
             dest="mlmmjListBase",
             help="Directory containing mlmmj list sub directories");
p.add_option("-f",
             "--pid-file",
             dest="mlmmjAdmPidFile",
             help="Where to write a pid file. No pid file is written if this parameter is not used");
p.add_option("-e",
            "--daemonize",
            dest="daemonize",
            action="store_true",
            help="Cause mlmmjadmd to fork to the background");
p.add_option("-c",
             "--configuration-file",
             dest="mlmmjAdmConfigFile",
             help="Where to look for the mlmmjadmd config file");
p.add_option("-i",
             "--user",
             dest="mlmmjAdmUser",
             help="If specified, mlmmjadmd will change the process owner to this user");
p.add_option("-g",
             "--group",
             dest="mlmmjAdmGroup",
             help="If specified, mlmmjadmd will change its group to the one specified");
p.add_option("-t",
             "--list-texts-dir",
             dest="mlmmjListTextsDir",
             help="Where to look for list texts used when creating new lists.");
(options, args) = p.parse_args();

if options.mlmmjAdmLogFile:
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                        datefmt='%m-%d %H:%M:%S',
                        filename=options.mlmmjAdmLogFile,
                        filemode='w');
else:
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                        datefmt='%m-%d %H:%M:%S',
                        filemode='w');

configuration.load();
if options.mlmmjAdmConfigFile:
    configuration.load(options.mlmmjAdmConfigFile);
if options.mlmmjAdmDebug:
    configuration.setDebug(options.mlmmjAdmDebug);
if not configuration.getDebug():
    logging.disable(logging.INFO);
if options.mlmmjListTextsDir:
    configuration.setMlmmjListTextsDir(options.mlmmjListTextsDir);
if options.mlmmjAdmGroup:
    configuration.setGroup(options.mlmmjAdmGroup);
if options.mlmmjAdmUser:
    configuration.setUser(options.mlmmjAdmUser);
if options.mlmmjAdmBindAddress:
    configuration.setBindAddress(options.mlmmjAdmBindAddress);
if options.mlmmjAdmBindPort:
    try:
        configuration.setBindPort(int(options.mlmmjAdmBindPort));
    except ValueError, e:
        logging.fatal("Binding port must be a number. Exiting.");
        sys.exit(1);
if options.mlmmjAdmUsers:
    configuration.setUsersFile(options.mlmmjAdmUsers);
if options.mlmmjAdmLogFile:
    configuration.setLogFile(options.mlmmjAdmLogFile)
if options.mlmmjBinPrefix:
    configuration.setMlmmjBinPrefix(options.mlmmjBinPrefix);
if options.mlmmjListBase:
    configuration.setListBase(options.mlmmjListBase);
if options.mlmmjAdmPidFile:
    configuration.setPidFile(options.mlmmjAdmPidFile);

if options.daemonize:
    logging.debug("Deamonizing...");
    mlmmjadm.util.daemonize();

if options.mlmmjAdmPidFile:
    configuration.setPidFile(options.mlmmjAdmPidFile);
    writePidFile(configuration.getPidFile());

if configuration.getUser():
    mlmmjadm.util.setEffectiveUser(configuration.getUser());
if configuration.getGroup():
    mlmmjadm.util.setEffectiveGroup(configuration.getGroup());


# Ensure that the commandline/configuration file
# parameters supplied are valid.
configuration.checkConfiguration();

logging.debug("Creating server...");
logging.debug("Binding to "+configuration.getBindAddress()+":"+str(configuration.getBindPort()));

try:
    server = Server((configuration.getBindAddress(), configuration.getBindPort()), 
                    ServerRequestHandler);
except Exception, e:
    logging.fatal("Unable to bind to address/port ("+str(e)+"). Exiting");
    sys.exit(1);
                
server.allow_reuse_address = True;
logging.debug("Installing signal handlers...");
signal.signal(signal.SIGHUP, hupHandler);
signal.signal(signal.SIGQUIT, quitHandler);
logging.debug("Listening for connections...");
try:
    server.serve_forever();
except KeyboardInterrupt, e:
    logging.fatal("Caught keyboard interrupt. Exiting.");
    sys.exit(1);