#####################################################################
#####################################################################
# fluxspace.process - Fluxspace process management module
#####################################################################
#####################################################################

import os
import re
import stat
import string
import signal

reps = re.compile('^[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+(.+)[ \t\r\n]*$')

reNumDir = re.compile('^[0-9]+$')
rePPID   = re.compile('^PPid:[ \t]+([0-9]+)[ \t]*$')

rootMenuFile = os.environ['HOME'] + '/GNUstep/Defaults/WMRootMenu'

def GetProcessPath(pid = 0, file = ''):
	path = '/proc'
	if pid:
		path = path + ( '/%s' % pid )
	if file:
		path = path + ( '/%s' % file )
	return path

def GetUserPIDs(matchUser):
    pids = []
    for subdir in os.listdir(GetProcessPath()):
        procdir = GetProcessPath(subdir)
        statInfo = os.stat(procdir)
        mode  = statInfo[stat.ST_MODE]
        isDir = stat.S_ISDIR(mode)
        user  = statInfo[stat.ST_UID]
        if isDir and reNumDir.search(subdir) != None:
            if user == matchUser:
                pids.append(int(subdir))
    return pids

def GetProcessCommand(pid):
	cmdlinefile = GetProcessPath(pid, 'cmdline')
	cmdline = open(cmdlinefile, 'r').readline()
	chunks = string.split(cmdline, '\0')
	return chunks

def GetProcessUser(pid):
    return os.stat(GetProcessPath(pid))[stat.ST_UID]

def GetProcessParent(pid):
    parent = 0
    for line in open(GetProcessPath(pid, 'status')).readlines():
        matchPPID = rePPID.match(line)
        if matchPPID != None:
            parent = int(matchPPID.group(1))
    return parent

class Process:

    def __init__(self, pid):
        self.pid      = pid
        self.uid      = GetProcessUser(pid)
        self.ppid     = GetProcessParent(pid)
        self.parent   = None
        self.children = []

        cmdParts  = self.GetProcessCommand()
        args = ""
        for i in range(1, len(cmdParts)):
            if i > 0:
                args = args + " "
            args = args + cmdParts[i]

        self.command  = cmdParts[0]
        self.args     = args
        pathParts = string.split(self.command, '/')
        self.commandName = pathParts[len(pathParts)-1]

        self.GetStatus()

    def GetStatus(self):
        self.name  = '???'
        statusfile = self.GetPath('status')
        for line in open(statusfile).readlines():
            fields = line.split()
            if fields[0].lower() == 'name:':
                self.name = fields[1]

    def GetProcessCommand(self):
        cmdlinefile = self.GetPath('cmdline')
        cmdline = open(cmdlinefile, 'r').readline()
        chunks = string.split(cmdline, '\0')
        return chunks

    def GetPath(self, file = ''):
        return GetProcessPath(self.pid, file)

    def AddChild(self, child):
        self.children.append(child)
        child.parent = self

    def Kill(self, children = 0):
        if children:
            for child in self.children:
                child.Kill(1)
        os.kill(self.pid, signal.SIGINT)

    def IsCurrent(self):
        if self.pid == os.getpid():
            return 1
        if self.parent is not None:
            return self.parent.IsCurrent()
        return 0

class Processes:
    def __init__(self):
        self.thisUID = os.getuid()
        self.Refresh()

    def Refresh(self):
        self.byPID   = {}
        self.byName  = {}
        self.ordered = []
        self.tree    = []
        # Create the flat list of processes
        # Also build the name dictionary
        for pid in GetUserPIDs(self.thisUID):
            newProcess = Process(pid)
            self.byPID[pid] = newProcess
            self.ordered.append(newProcess)
            if not self.byName.has_key(newProcess.name):
                self.byName[newProcess.name] = []
            self.byName[newProcess.name].append(newProcess)
        # Build the tree structure
        for process in self.ordered:
            if self.byPID.has_key(process.ppid):
                self.byPID[process.ppid].AddChild(process)
            else:
                 self.tree.append(process)

    def Find(self, name):
        processes = []
        if self.byName.has_key(name):
            for process in self.byName[name]:
                if not process.IsCurrent():
                    processes.append(process)
        return processes
        
    def KillByName(self, name, children = 0):
        for process in self.Find(name):
            if not process.IsCurrent():
                process.Kill(1)


syntax highlighted by Code2HTML, v. 0.9.1