Logo Search packages:      
Sourcecode: iacd version File versions  Download package

iacd.c

#define _GNU_SOURCE

#include "config.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <fcntl.h>

#include <pwd.h>
#include <grp.h>

#include "util.h"
#include "net.h"
#include "log.h"
#include "irc.h"
#include "timer.h"
#include "conf.h"
#include "servlink.h"
#include "dns.h"

iac_server_configuration_t iac_cfg;
iac_server_status_t iac_status;
iac_cmd_usage_t iac_cmd_usage;

int iac_serv_closed = 0;
int iac_client_closed = 0;
int iac_using_pidfile = 0;
fd_set iac_rfds;
rl_htable_t *iac_users = NULL;
rl_htable_t *iac_channels = NULL;
rl_list_t *iac_client_conns = NULL;
rl_list_t *iac_server_conns = NULL;
char *iac_motd = NULL;
long iac_starttime = 0;

#ifndef HAVE_IPV6
struct dns_resolver resolvers[IAC_MAX_DNS_RESOLVERS];
#endif

void
iac_atexit(void)
{
      iac_net_stop();

      if (iac_users)
            rl_hashtable_del(iac_users);

      if (iac_channels)
            rl_hashtable_del(iac_channels);

    if (iac_motd)
        RL_FREE(iac_motd);

    if (iac_cfg.flags & IAC_DAEMON && !iac_cfg.chroot[0])
            closelog();

    if ( iac_cfg.pid_file[0] )
        remove( iac_cfg.pid_file );
}

void
iac_sighup(int unused)
{
    iac_cfg.flags |= IAC_REHASH;
}

void
iac_sigterm(int unused)
{
      exit(0);
}


int
main(int argc, char *argv[])
{
      int                   i;
    struct rlimit         rl;
    iac_server_t *        s;
    char                  domain[256];

    struct passwd *       uentry = NULL;
    struct group *        gentry = NULL;

    memset(&iac_cfg, 0, sizeof(iac_server_configuration_t));
    memset(&iac_status, 0, sizeof(iac_server_status_t));
    memset(&iac_cmd_usage, 0, sizeof(iac_cmd_usage_t));

#ifndef HAVE_IPV6
    memset(resolvers, 0, sizeof(struct dns_resolver) * IAC_MAX_DNS_RESOLVERS);
#endif
  
    iac_safe_strncpy(iac_cfg.logprefix, "logs", sizeof(iac_cfg.logprefix));

    snprintf ( iac_cfg.configfile, sizeof(iac_cfg.configfile), "%s/iacd.conf", SYSCONFDIR );

    iac_safe_strncpy(iac_cfg.info, "irc server", sizeof(iac_cfg.info));


    /*
     * create some lists and hashtables
     */
      iac_users = rl_hashtable_new(100, 37, RL_HTABLE_DONT_FREE_DATA);
      iac_channels = rl_hashtable_new(100, 37, RL_HTABLE_DONT_FREE_DATA);


    /*
     * save start time to calculate uptime
     */
    iac_starttime = time(0);

    /*
     * parse arguments
     */
      argc--;
      i=1;
      while(argc != 0) {
        if (!rl_stricmp(argv[i], "-f"))
        {
            if (argc > 1) {
                iac_safe_strncpy(iac_cfg.configfile, argv[++i],
                    sizeof(iac_cfg.configfile));
                argc--;
            }
            }
        else if (!rl_stricmp(argv[i], "-v"))
        {
            if (argc > 1) {
                if (!(iac_cfg.debug = atoi(argv[++i]))) iac_cfg.debug =0;
                argc--;
            }
            }
        else if (!rl_stricmp(argv[i], "-h"))
        {
                  printf("usage:\n");
                  printf("-d           run in background\n");
            printf("-f <file>    configuration file\n");
            printf("-u <user>    drop privs and change to this user\n");
            printf("-g <group>   drop privs and change to this group\n");
            printf("-c <path>    chroot() to this path\n");
                  printf("-v <level>   verbose output\n");
                  printf("-p <pidfile> create a pidfile\n");
                  exit(0);
            }
        else if ( !rl_stricmp ( argv[i], "-u" ) )
        {
            if ( argc > 1 )
            {
                iac_safe_strncpy ( iac_cfg.user, argv[++i],
                        sizeof(iac_cfg.user) );
                argc--;
            }

        }
        else if ( !rl_stricmp ( argv[i], "-g" ) )
        {
            if ( argc > 1 )
            {
                iac_safe_strncpy ( iac_cfg.group, argv[++i],
                        sizeof(iac_cfg.group) );
                argc--;
            }

        }
        else if (!rl_stricmp(argv[i], "-c"))
        {
            if ( argc > 1 )
            {
                iac_safe_strncpy( iac_cfg.chroot, argv[++i],
                        sizeof(iac_cfg.chroot));
                argc--;
            }
        }
        else if (!rl_stricmp(argv[i], "-d"))
        {

#ifdef HAVE_DAEMON

                  if (daemon(0, 0) < 0)
                        iac_log(IAC_ERR, "daemon() failed: %s\n", strerror(errno));

#else
            pid_t pid = fork();

            if ( pid == -1 )
            {
                iac_log(IAC_ERR, "fork() failed: %s\n", strerror(errno));
            } 
            else if ( pid == 0 )
            {
                /*
                 * child
                 */
                close(0);
                close(1);
                close(2);
                chdir("/");
                setsid();
            } 
            else
            {
                /*
                 * parent
                 */
                _exit(0);
            }
#endif

                  openlog("ircd", 0, LOG_DAEMON);
            iac_cfg.flags |= IAC_DAEMON;
            }
        else if ( !rl_stricmp(argv[i], "-p") )
        {
            if (argc > 1) {
                int f, pid;
                char s[128];

                iac_safe_strncpy( iac_cfg.pid_file, argv[++i],
                        sizeof(iac_cfg.pid_file));

                if ( (f = open( iac_cfg.pid_file, O_WRONLY | O_CREAT | O_EXCL, 0644 )) < 0 ) {
                    fprintf( stderr, "Unable to create pid file: %s\n", strerror( errno ) );
                    fprintf( stderr, "iacd wasn't shutdown properly, use the quit button in the start menu ;)\n" );
                    fprintf( stderr, "Nahh, just remove the pidfile %s\n", iac_cfg.pid_file );
                    exit( -1 );
                }

                pid = getpid();
                snprintf( s, sizeof(s), "%d\n", pid );
                write( f, s, strlen(s) );
                close( f );

                iac_using_pidfile = 1;

                argc--;
            }
        }
            i++;
            argc--;
      }

    /*
     * get my own hostname
     */
    errno = 0;
    if ( gethostname(iac_cfg.servername, sizeof(iac_cfg.servername)) < 0) {
        iac_log(IAC_WARN, "[WWW] - Unable to get hostname: %s\n",
            strerror(errno));
        strncpy(iac_cfg.servername, "localhost", sizeof(iac_cfg.servername));
    } else {
        iac_log(IAC_VERBOSE, "[   ] - My hostname: %s\n", iac_cfg.servername);
    }

    /*
     * get my own domainname
     */
    memset(domain, 0, sizeof(domain));
#ifdef HAVE_GETDOMAINNAME
    if ( getdomainname(domain, sizeof(domain)) < 0 ) {
        iac_log(IAC_WARN, "[WWW] - Unable to get domainname: %s\n",
            strerror(errno));
    }
#else
  
    /*
     * does not work, tgr 05/28/02
     */
#if 0
    if ( sysinfo ( SI_SRPC_DOMAIN, domain, sizeof(domain) ) < 0 ) {
        iac_log(IAC_WARN, "[WWW] - Unable to get domainname: %s\n",
            strerror(errno));
    }
#endif
    
#endif

    if ( *domain ) {
        iac_log(IAC_VERBOSE, "[   ] - My domainname: %s\n", domain);
        strncat(iac_cfg.servername, ".",
            sizeof(iac_cfg.servername) - strlen(iac_cfg.servername) - 1);
        strncat(iac_cfg.servername, domain,
            sizeof(iac_cfg.servername) - strlen(iac_cfg.servername) - 1);
    }

    iac_log(IAC_VERBOSE, "[   ] - My FQDN: %s\n", iac_cfg.servername);

    /*
     * do some cleanups before quiting
     */
    iac_log(IAC_DEBUG, "[   ] - Installing exit() handler\n");
      errno = 0;
      if (atexit(&iac_atexit) < 0)
            iac_log(IAC_ERR, "atexit() failed: %s\n", strerror(errno));

    /*
     * quit on SIGTERM
     */
    iac_log(IAC_DEBUG, "[   ] - Installing SIGTERM handler\n");
      errno = 0;
      if (signal(SIGTERM, &iac_sigterm) == SIG_ERR)
            iac_log(IAC_ERR, "signal(SIGTERM) failed: %s\n", strerror(errno));

    /*
     * rehash some config on SIGHUP
     */
    iac_log(IAC_DEBUG, "[   ] - Installing SIGHUP handler\n");
      errno = 0;
      if (signal(SIGHUP, &iac_sighup) == SIG_ERR)
            iac_log(IAC_ERR, "signal(SIGHUP) failed: %s\n", strerror(errno));

    /*
     * ignore SIGPIPE
     */
    iac_log(IAC_DEBUG, "[   ] - Installing SIGPIPE handler\n");
    errno = 0;
    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
        iac_log(IAC_ERR, "signal(SIGPIPE) failed; %s\n", strerror(errno));

    iac_log(IAC_DEBUG, "[   ] - Seeding\n");
    srand(time(0));

    /*
     * set max fd's open of this process. a higher value than
     * 1024 will need r00t privileges.
     */
    rl.rlim_cur = (long) IAC_MAX_SOCK_CONNECTS;
    rl.rlim_max = (long) IAC_MAX_SOCK_CONNECTS;

    iac_log(IAC_DEBUG, "[   ] - Setting RLIMIT_OFILE to %ld\n",
        IAC_MAX_SOCK_CONNECTS);
#if 0
    errno = 0;
    if ( setrlimit(RLIMIT_OFILE, &rl) < 0 ) {
        iac_log(IAC_ERR, "setrlimit failed: %s\n", strerror(errno));
    }
#endif

    if ( iac_cfg.group[0] )
    {
        if ( !(gentry = getgrnam ( iac_cfg.group )) )
        {
            iac_log ( IAC_ERR, "[EEE] - Unable to get group entry: %s\n", strerror(errno) );
        }
    }

    if ( iac_cfg.user[0] )
    {
        if ( !(uentry = getpwnam ( iac_cfg.user )) )
        {
            iac_log ( IAC_ERR, "[EEE] - Unable to get passwd entry: %s\n", strerror(errno) );
        }
    }


    /*
     * chroot!
     */
    if ( iac_cfg.chroot[0] )
    {
        if (iac_cfg.flags & IAC_DAEMON)
            closelog();

#ifdef HAVE_SCRIPTS
        iac_log( IAC_WARN, "[WWW] - Warning: You have scripts support compiled in. Using chroot() might prevent you from using perl, sh, etc.");
#endif


        if ( chroot( iac_cfg.chroot ) < 0 )
            iac_log( IAC_ERR, "[EEE] - chroot(%s) failed: %s\n", iac_cfg.chroot, strerror(errno) );
    }

    iac_conf_read(NULL, iac_cfg.configfile);

    iac_conf_interpret();

    if (iac_cfg.motdfile[0] != '\0')
        iac_irc_read_motd(iac_cfg.motdfile);


    if ( gentry )
    {
        if ( setgid ( gentry->gr_gid ) < 0 )
        {
            iac_log ( IAC_ERR, "[EEE] - Unable to set group id: %s\n", strerror(errno) );
        }
    }

    if ( uentry )
    {
        if ( setuid ( uentry->pw_uid ) < 0 )
        {
            iac_log ( IAC_ERR, "[EEE] - Unable to set user id: %s\n", strerror(errno) );
        }
    }

    

    if ( !(s = (iac_server_t *) malloc(sizeof(iac_server_t))) )
        iac_log(IAC_ERR, "Out of memory\n");
    memset(s, 0, sizeof(iac_server_t));

    s->name = strdup(iac_cfg.servername);
    s->info = strdup(iac_cfg.info);
    s->numeric = iac_cfg.numeric;
    iac_status.servers = s;
    
    iac_net_start(iac_cfg.client_port, iac_cfg.server_port);

    iac_irc_check_pong("");
    iac_servlink_check_pong("");
#ifdef IAC_AUTOAWAY
    iac_irc_check_auto_away("");
#endif

    iac_servlink_autoconnect();
    
    for (;;) {

        iac_net_handle();

        if ( iac_cfg.flags & IAC_REHASH ) {
            iac_conf_read(NULL, iac_cfg.configfile);
            iac_conf_interpret();

            iac_cfg.flags &= ~(IAC_REHASH);
        }
    }
    
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index