/*
 *   MediaMVP Server
 *
 *   (C) 2003 Dominic Morris
 *
 *   $Id: main.c,v 1.10 2004/04/25 16:40:24 dom Exp $
 *   $Date: 2004/04/25 16:40:24 $
 *
 *
 *   Startup..
 */

#include <signal.h>
#include <pwd.h>


#include "program.h"



static char       *c_interface       = NULL;
static char 	  *c_log_file        = NULL;
static char	      *c_pid_file        = NULL;
static char        c_daemon          = 0;
static char        c_help            = 0;
static char       *c_config_file     = "mediamvp.conf";
static char       *c_user            = NULL;

mvpinit_t   init = MVPINIT_INITIALISER;

void clean_up_files()
{
    /* Close the log file if we opened it */
    if( init.logfile != NULL ) {
        fclose(init.logfile);
    }

    /* Remove the pid file */
    if( c_pid_file != NULL ) {
        unlink(c_pid_file);
    }
}

void close_on_signal(int signal)
{
    Dprintf(INFO,"Close on signal %d\n", signal);
      
    clean_up_files();

    exit(0);
}

int main(int argc, char *argv[])
{
    char hostbuf[2048];


    /* Set up signal handling */
    signal(SIGINT, close_on_signal);
    signal(SIGTERM, close_on_signal);

    iniparse_init("main");

    iniparse_add('f',"main:config-file","Configuration file location",OPT_STR,&c_config_file);

    iniparse_add(0,"main:interface","IP address of interface to listen on",OPT_STR,&c_interface);
    iniparse_add(0,"main:dongleversion","Dongle version to be compatible with",OPT_INT,&init.dongle_version);
    iniparse_add(0,"main:streamport","Port to listen on for media connections",OPT_INT,&init.stream_port);
    iniparse_add(0,"main:guiport","Port to listen on for gui connections",OPT_INT,&init.gui_port);
    iniparse_add(0,"main:mpegbufsize","Amount of prebuffering for video files",OPT_INT,&init.mpeg_bufsize);
    iniparse_add(0,"main:mp3bufsize","Amount of prebuffering for audio files",OPT_INT,&init.mp3_bufsize);

    /* Debug level */
    iniparse_add(0,"main:debuglevel","Debug level for server",OPT_INT,&init.debug_level);

    /* Redirect output to a log file */
    iniparse_add(0,"main:logfilename","File to output debug info to",OPT_STR,&c_log_file);
    /* Start the console as a daemon */
    iniparse_add('d',"main:daemon","Run server as a daemon",OPT_BOOL,&c_daemon);
    iniparse_add(0,"main:pidfilename","File to place pid in",OPT_STR,&c_pid_file);

    iniparse_add('h',"main:help","Display this help information",OPT_BOOL,&c_help);
#ifndef WIN32
    iniparse_add('u',"main:user","User to run program as ",OPT_STR,&c_user);
#endif
    program_config();

    /* Parse arguments to get out things that affect the location of the
       config file
    */
    iniparse_args(argc,argv);

    if ( iniparse_file(filename_expand(c_config_file)) || c_help ) {
        printf("MediaMVP server, version %s\n",SERVER_VERSION);
        printf("Options:\n\n");
        iniparse_help(stdout);
        printf("\n");
        exit(1);
    }

  

    iniparse_cleanup();



    if ( c_interface == NULL ) {
        if ( gethostname(hostbuf,sizeof(hostbuf)-1) == -1 ) {
            perror("gethostbyname");
            exit(1);
        }
        c_interface = hostbuf;
    }

    if ( ( init.main_interfaceip = host_resolve(c_interface) ) == - 1 ) {
        fprintf(stderr,"Cannot resolve host <%s>\n",c_interface);
        exit(1);
    }

    event_init();

    /* open the log file if specified */
    if ( c_log_file != NULL ) {
        fprintf(stderr, "Opening log file: %s\n", c_log_file);
        init.logfile = fopen(c_log_file, "w+");

        if (init.logfile == NULL) {
            perror(c_log_file);
            init.logfile = NULL;
        }
    } else {
        init.logfile = stderr;
    }

    /* Put the application into the background if necessary */
    if ( c_daemon ) {
        pid_t pid;
        if ( c_pid_file == NULL ) {
            c_pid_file = "/var/run/mediamvp.pid";
        }
        fprintf(stderr, "Starting in daemon mode\n");
        if( (pid = fork()) > 0) {
            FILE *pidfile = fopen(c_pid_file, "w");
            if( pidfile != NULL ) {
                fprintf(pidfile, "%d\n", pid);
                fclose(pidfile);
            }
            else {
                fprintf(stderr, "Unable to write pid to %s\n", c_pid_file);
                fprintf(stderr, "Pid = %d\n", pid);                
            }
            exit(0);
        }
    }

    program_init(&init);

    if ( mediamvp_server_init(&init) ) {
        exit(1);
    }


    /* Now we've bound to ports, switch users if necessary */
    if ( c_user ) {
        uid_t               saved_uid, uid;
        gid_t               saved_gid, gid;
        struct passwd      *pw;

        uid = (uid_t)atoi(c_user);
        
        if ( uid == 0 ) {
            pw = getpwnam(c_user);
            if ( pw ) {
                uid = pw->pw_uid;
                gid = pw->pw_gid;
            } else {
                uid = -1;
                gid = -1;
            }
        } else {
            pw = getpwuid(uid);

            gid = pw->pw_gid;
        }

        saved_uid = geteuid();
        saved_gid = getegid();
        
        if (seteuid(0) == 0) {
            if (gid != -1 && setegid(gid) != 0) {
                setegid(saved_gid);
            }
            
            if (uid != -1 && seteuid(uid) != 0) {
                seteuid(saved_uid);
            }
        } else {
            fprintf(stderr,"Cannot change users if not root\n");
        }
    }
    

   
    event_dispatch();

    clean_up_files();

    return 0;
}




/*
 * Local Variables:
 *  indent-tabs-mode:nil
 *  require-final-newline:t
 *  c-basic-offset: 4
 * End:
 */
