#!/usr/bin/env python

"""  Marcos Moyano - marcos@anue.biz

 Logout users of a specified period of idle time.

 Copyright (c) 2006 Marcos Moyano

 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License version 2 as published by
 the Free Software Foundation.
"""

__revision__ = "$Id: idleoutd 2007-6-11 $"
import os, sys, smtplib
from time import sleep
from re import compile as comp
from re import match
from logging import fatal, info, warning, DEBUG, getLogger, Formatter
from logging.handlers import RotatingFileHandler

G_FILE = "/etc/group"
P_FILE = "/etc/passwd"

### Necesary data ###
USR_BY_NAME = {}
GROUP_BY_NAME = {}
PROCS = {}
NO_BANN = []
BANN = {}
PRINTINFO = 0
PRINTVERSION = "0.8.1"
LOG_FLAG = 0

####################
# Manage arguments #
####################
if len(sys.argv[1:]) == 1:
    DEBUGG = sys.argv[1]
    if DEBUGG == "-D" or DEBUGG == "-d" or DEBUGG == "--debug":
        PRINTINFO = 1
    elif DEBUGG == "-h" or DEBUGG == "--help":
        printhelp()
        sys.exit(0)
    elif DEBUGG == "-v" or DEBUGG == "-V" or DEBUGG == "--version":
        print ("idleoutd version is: %s \n" % PRINTVERSION)
        sys.exit(0)
    else:
        print ("idleoutd: Invalid argument -- %s\n\
    Try 'idleoutd -h' or 'idleoutd --help' for more information." % DEBUGG)
        sys.exit(1)
elif len(sys.argv[1:]) > 1:
    print ("To many arguments: %d recieved, 1 expected.\n\
    Try 'idleoutd -h' or 'idleoutd --help'" % len(sys.argv[1:]))
    sys.exit(1)

#### End of manage arguments ####

##################
# Print Help Msg #
##################
def printhelp():
    """
    Print help information.
    """
    print """Logout users of a specified period of idle time.

Usage: idleoutd [OPTION]

   -D, -d, --debug          Print debug information to the screen every 60 seconds.
   -V, -v, --version        Print version information and exit.
   -h, --help               Print this help and exit.

Report bugs to <marcos@anue.biz>."""
    return

#### End of print help ####


######################
# Define logging way #
######################
def logg(LOG_FILE, LOG_SIZE):
    """
    Configuration of the log file.
    """
    RLOG = getLogger('')
    handler = RotatingFileHandler(LOG_FILE, 'a', LOG_SIZE * 1024 * 1024, 10)
    RLOG.addHandler(handler)
    R
LOG.setLevel(DEBUG)
    formatter = Formatter('%(asctime)s: %(levelname)-8s %(message)s','%b %d %H:%M:%S')
    handler.setFormatter(formatter)
    return

#### End of define logging ####

##################
# Get group info #
##################
def fetch_group(group, param):
    '''
    Fetch all the users in /etc/passwd with the same group id as "group".
    '''
    tmp = []

    gid = ""
    mygfile = open(G_FILE,'r')
    for lines in mygfile.readlines():
        line = lines.strip()
        name = line.split(':')[0]
        if group == name:
            gid = line.split(':')[2]
            break
    mygfile.close()
    mypfile = open(P_FILE,'r')
    for lines in mypfile.readlines():
        line = lines.strip()
        guid = line.split(':')[3]
        if gid == guid:
            tmp.append(line.split(":")[0])
    mypfile.close()
    GROUP_BY_NAME[group] = (tmp, param)
    return (GROUP_BY_NAME)

#### End of get group info ####

#################
# Group defined #
#################
def group_define(spar, param):
    """
    Fetch users from the specified group.
    """
    idle_time = param[0].split("=")[1]
    GROUP_BY_NAME = fetch_group(spar, param)
    try:
        filed = open(G_FILE,'r')
        for lines in filed.readlines():
            line = lines.strip()
            if spar == str(line.split(':')[0]):
                tmp = line.split(':')
                groups = tmp[len(tmp)-1]
        filed.close()
        lofusr = GROUP_BY_NAME[spar][0]
        groups = groups.split(',')
        for x in lofusr:
            if x not in groups:
                groups.append(x)
        if int(idle_time) == 0:
            for x in groups:
                if x not in NO_BANN:
                    NO_BANN.append(x)
                for y in GROUP_BY_NAME.keys():
                    if x in GROUP_BY_NAME[y][0]:
                        GROUP_BY_NAME[y] = (GROUP_BY_NAME[y][0][1:], param)
                    if GROUP_BY_NAME[y][0] == []:
                        del GROUP_BY_NAME[y]
        else:
            for usr in groups:
                if usr not in NO_BANN:
                    GROUP_BY_NAME[spar] = (groups, param)
    except Exception, err:
        warning("%s -> %s " % (err.__class__ , err))
        warning("I was unable to open file %s." % G_FILE)

#### end of group definded ####

################
# User defined #
################
def usr_define(spar, param):
    """
    Fetch the specified user.
    """
    try:
        filed = open(P_FILE,'r')
        for lines in filed.readlines():
            line = lines.strip()
            user = str(line.split(':')[0])
            if spar == user:
                itime = int(param[0].split('=')[1])
                if itime == 0:
                    if spar not in NO_BANN:
                        NO_BANN.append(spar)
                else:
                    if spar in NO_BANN:
                        NO_BANN.remove(spar)
                    USR_BY_NAME[spar] = param
        filed.close()
        if spar not in USR_BY_NAME.keys() and spar not in NO_BANN:
            info("Config file --> User %s is not defined in system." % spar)
    except Exception, err:
        warning("%s -> %s " % (err.__class__ , err))
        warning("I was unable to open file %s." % P_FILE)

#### end of user definded ####

##################
#    Get info    #
##################
def get_info(LOG_FLAG):
    """
    Parse the configuration file.
    """
    try:
        from idleoutconf import log, logsize, pid, host, port, domain
        from idleoutconf import group, name
        if LOG_FLAG != 1:
            logg(log, int(logsize))
            # Don't open another logging instance!
            LOG_FLAG = 1
        global smtp
        smtp = [host, int(port), domain]
        reg1 = comp('(\s+)\=(\s+)')
        for users in name:
            users = reg1.sub("=", users.strip())
            usrtmp = users.split()
            usrname = usrtmp[0]
            rest = usrtmp[1:]
            usr_define(usrname, rest)
        for groups in group:
            groups = reg1.sub("=", groups.strip())
            grtmp = groups.split()
            groupname = grtmp[0]
            rest = grtmp[1:]
            group_define(groupname, rest)
        return(pid)
    except Exception, err:
        print >> sys.stderr, "Error: %d: %s" % (err.errno, err.strerror)
        sys.exit(err.errno)

#### end get info ####

##################
#  Compute info  #
##################
def compute(process):
    """
    Manage all the information and call the require events.
    """
    tmp = [x for x, y in BANN.iteritems() if x not in process.keys()]
    for x in tmp:
        del BANN[x]             	# Clean people who got back
    for x, y in process.iteritems():
        user = x.split(',')[0]
        dev = x.split(',')[1]
        time = int(y[0])
        # Search in user define dictionary
        if USR_BY_NAME.has_key(user):
            idtm = int(USR_BY_NAME[user][0].split('=')[1])
            if time >= idtm:
                grace = int(USR_BY_NAME[user][1].split('=')[1])
                silent = USR_BY_NAME[user][3].split('=')[1]
                if x in BANN.keys():
                    if BANN[x] >= grace:
                        del BANN[x]
                        if silent == "no":
                            bann_usr(x, y[1], grace, 0)  # Bann the user
                        else:
                            # Bann the user with silent
                            bann_usr(x, y[1], grace, 1)
                        mail = USR_BY_NAME[user][2].split('=')[1]
                        if mail == "yes":
                            send_mail(user, dev)
                    else:
                        BANN["%s" % x] = int(BANN[x]) + 1
                else:
                    ret = checkcon(x)
                    if ret == 0:
            