Ahenk/usr/share/ahenk/helper/system.py
2020-04-06 18:10:41 +03:00

74 lines
2.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os, signal
class ProcEntry(object):
def __init__(self, name, pid, cmdline, euid, egid):
super(ProcEntry, self).__init__()
self.name = name
self.pid = pid
self.cmdline = cmdline
self.euid = euid
self.egid = egid
def __str__(self):
return 'name: {0}, pid: {1}, uid: {2}, gid: {3}, cmd: {4}' \
.format(self.name, self.pid, self.euid, self.egid, self.cmdline)
class ProcParseError(Exception):
def __init__(self, msg):
super(Exception, self).__init__(msg)
def proclist():
def raise_if_less(l, n):
if len(l) < n:
raise ProcParseError('too few fields, expected at least ' + str(n))
for pid in [pid for pid in os.listdir('/proc') if pid.isdigit()]:
p = os.path.join('/proc', pid, 'cmdline')
cmdline = open(p).read()
p = os.path.join('/proc', pid, 'status')
euid = None
egid = None
name = None
for lin in open(p):
if lin.startswith('Name:'):
s = lin.split()
raise_if_less(s, 2)
name = s[1]
elif lin.startswith('Uid:'):
uid_line = lin.split()
raise_if_less(uid_line, 3)
euid = int(uid_line[2])
elif lin.startswith('Gid:'):
gid_line = lin.split()
raise_if_less(gid_line, 3)
egid = int(gid_line[2])
yield ProcEntry(name, int(pid), cmdline, euid, egid)
PATH_SHELLS='/etc/shells'
def login_shells():
valid = lambda s: s.rstrip(' \n') and not s.lstrip(' \t').startswith('#')
return [lin.rstrip('\n') for lin in open(PATH_SHELLS).readlines()
if valid(lin)]
def shell_is_interactive(sh):
shells = ['sh', 'bash', 'dash', 'zsh', 'fish', 'ksh', 'csh', 'tcsh']
return any(s == os.path.basename(sh) for s in shells)
def killuserprocs(uid):
for p in proclist():
if p.euid == uid:
try:
os.kill(p.pid, signal.SIGTERM)
except ProcessLookupError as e:
# The process might have died immediately, up till now, even
# before we had a chance to send a signal to it.
pass