1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
# UpdateManager/Util/processinfo.py
#
# Copyright (c) 2009 Canonical
# 2009 Stephan Peijnik
#
# Author: Stephan Peijnik <debian@sp.or.at>
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
import logging
import os
LOG = logging.getLogger('UpdateManager.Util.procesinfo')
class ProcessInfo(object):
""" Process info representation """
def __init__(self, pid):
assert(type(pid) == int)
self._pid = pid
self._owner_uid = None
self._parent_pid = None
self._name = None
self._parent = None
self._ready = False
self.__read_info()
def __read_info(self):
""" Reads the process info from /proc/<pid>/status """
path = os.path.join('/proc/', str(self._pid), 'status')
assert(os.path.exists(path))
try:
fp = open(path, 'r')
for line in fp.readlines():
data = line.strip().split('\t')
name = data[0]
if name == 'PPid:':
self._parent_pid = int(data[1])
elif name == 'Uid:':
self._owner_uid = int(data[1])
# TODO: What can we use data[2:] for? What does it mean?
elif name == 'Name:':
self._name = data[1]
fp.close()
except IOError, e:
LOG.error('IO Error occured: %s', e)
@property
def parent(self):
""" Parent ProcessInfo object """
if self._parent is not None:
return self._parent
if self._parent_pid != 0:
self._parent = ProcessInfo(self._parent_pid)
return self._parent
@property
def pid(self):
""" Process ID """
return self._pid
@property
def owner_uid(self):
""" Process owner UID """
return self._owner_uid
@property
def name(self):
""" Process name """
return self._name
def __repr__(self):
return '<ProcessInfo(pid=%d, name=%s, owner_uid=%s, parent_pid=%s)' %\
(self._pid, self._name, self._owner_uid, self._parent_pid)
def find_nonroot_parent():
"""
Finds the first parent process that is not owned by root, starting
at the current process.
:returns: :class:`ProcessInfo` object or None
"""
my_pid = os.getpid()
my_proc = ProcessInfo(my_pid)
if my_proc.owner_uid != 0:
return my_proc
parent_proc = my_proc.parent
while parent_proc:
LOG.debug('Proc: %r', parent_proc)
if parent_proc.owner_uid != 0:
break
parent_proc = parent_proc.parent
return parent_proc
|