#!/usr/bin/python

## system-config-printer
## CUPS backend
 
## Copyright (C) 2002, 2003 Red Hat, Inc.
## Copyright (C) 2002, 2003 Tim Waugh <twaugh@redhat.com>
 
## This program 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.
 
## This program 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 this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import os
import signal
import sys

nmblookup = "/usr/bin/nmblookup"
smbclient = "/usr/bin/smbclient"

def get_host_list ():
    """Return a dict, indexed by SMB name, of host dicts for this network.

    A host dict has 'NAME' and 'IP' keys, and may have a 'GROUP' key."""

    hosts = {}
    if not os.access (nmblookup, os.X_OK):
        return hosts

    ips = []
    signal.signal (signal.SIGCHLD, signal.SIG_DFL)
    for l in os.popen ("LANG=C %s '*'" % nmblookup, 'r').readlines ():
        if l.endswith (" *<00>\n"):
            ips.append (l.split (" ")[0])

    for ip in ips:
        name = None
        dict = { 'IP': ip }
        signal.signal (signal.SIGCHLD, signal.SIG_DFL)
        for l in os.popen ("LANG=C %s -A '%s'" % (nmblookup, ip),
                           'r').readlines ():
            l = l.strip ()
            if l.find (" <00> ") == -1:
                continue

            try:
                val = l.split (" ")[0]
                if val.find ("~") != -1:
                    continue

                if l.find (" <GROUP> ") != -1 and not dict.has_key ('GROUP'):
                    dict['GROUP'] = l.split (" ")[0]
                elif not dict.has_key ('NAME'):
                    name = l.split (" ")[0]
                    dict['NAME'] = name
            except:
                pass

        if not name:
            continue

        hosts[name] = dict

    return hosts

def get_host_info (smbname):
    """Given an SMB name, returns a host dict for it."""
    dict = { 'NAME': smbname, 'IP': '', 'GROUP': '' }
    for l in os.popen ("LANG=C %s -S '%s'" % (nmblookup, smbname),
                       'r').readlines ():
        l = l.strip ()
        if l.endswith ("<00>"):
            dict['IP'] = l.split (" ")[0]
            continue

        if l.find (" <00> ") == -1:
            continue

        if l.find (" <GROUP> ") != -1:
            dict['GROUP'] = l.split (" ")[0]
        else:
            name = l.split (" ")[0]
            dict['NAME'] = name

    return dict

def get_printer_list (host):
    """Given a host dict, returns a dict of printer shares for that host.
    The value for a printer share name is its comment."""

    printers = {}
    if not os.access (smbclient, os.X_OK):
        return printers

    str = "LANG=C %s -N -L '%s'" % (smbclient, host['NAME'])
    if host.has_key ('IP'):
	str += " -I '%s'" % host['IP']

    if host.has_key ('GROUP'):
        str += " -W '%s'" % host['GROUP']

    signal.signal (signal.SIGCHLD, signal.SIG_DFL)
    section = 0
    for l in os.popen (str, 'r'):
        l = l.strip ()
        if l == "":
            continue

        if l[0] == '-':
            section += 1
            if section > 1:
                break

            continue

        if section != 1:
            continue

        share = l[:l.find (" ")]
        rest = l[len (share):].strip ()
        end = rest.find (" ")
        if end == -1:
            type = rest
            comment = ""
        else:
            type = rest[:rest.find (" ")]
            comment = rest[len (type):].strip ()

        if type == "Printer":
            printers[share] = comment

    return printers

def printer_share_accessible (share, group = None, user = None, passwd = None):
    """Returns None if the share is inaccessible.  Otherwise,
    returns a dict with 'GROUP' associated with the workgroup name
    of the server."""

    if not os.access (smbclient, os.X_OK):
        return None

    args = [ smbclient, share ]
    if passwd:
        args.append (passwd)
    else:
        args.append ("-N")

    if group:
        args.extend (["-W", group])

    args.extend (["-c", "quit"])
    if user:
        args.extend (["-U", user])

    read, write = os.pipe ()
    signal.signal (signal.SIGCHLD, signal.SIG_DFL)
    pid = os.fork ()
    if pid == 0:
        os.close (read)
        if write != 1:
            os.dup2 (write, 1)

        os.environ['LANG'] = 'C'
        os.execv (args[0], args)
        sys.exit (1)

    # Parent
    dict = { 'GROUP': ''}
    os.close (write)
    for l in os.fdopen (read, 'r').readlines ():
        if l.startswith ("Domain=[") and l.find ("]") != -1:
            dict['GROUP'] = l[len("Domain=["):].split ("]")[0]
            break

    pid, status = os.waitpid (pid, 0)
    if status:
        return None

    return dict

if __name__ == '__main__':
    hosts = get_host_list ()
    print get_printer_list (hosts[hosts.keys ()[0]])
