#!/usr/bin/env python

# reniceall - like killall but nicer.  (renice a list of programs by name)
# Probably there's already a program that does this, but meh.  Meh, I say!

# Copyright 2011 Nathan P. Stien
# originally written in 2003, redone in 2011 for shits/giggles

import sys, os

def isInt(x):
    """ decide if a string can be parsed as an integer. """
    try:
        y = int(x)
        return True
    except ValueError:
        return False

def getProcName(pid):
    """ read a process's name out of /proc/<pid>/status. """
    f = file('/proc/%s/status' % pid,'r')
    line = f.readline()  # just read first line
    f.close()    
    assert line[:5] == 'Name:'
    return line[6:].strip()    

def listProcs():
    """ find all processes on the system, returned as (pid, name) pairs. """
    return [ (pid, getProcName(pid)) for pid in os.listdir("/proc/") if isInt(pid) ]


def main(argv):
    if len(argv) < 3:
        print 'USAGE: %s priority prog0 [prog1 [prog2..]]' \
                % os.path.split(argv[0])[1]
        print 'This program will find all process matching the specified'
        print 'command names and attempt to renice them to the specified'
        print 'priority.  Hooray.'
        return -1
    
    try:
        priority = int(argv[1])
    except ValueError:
        sys.stderr.write('ERROR: Priority must be specified as an integer.')
        return -2       
    
    targetNames = argv[2:]
    pids = [ pid for (pid,pname) in listProcs() if pname in targetNames ]
    os.system('renice %d %s' % (priority, ' '.join(pids)))
    

if __name__ == '__main__':
    sys.exit(main(sys.argv))
