Advertisement
Guest User

Untitled

a guest
Jul 5th, 2019
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.91 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. #
  3. # Send a GUI notification to all logged-in users.
  4. # Written by https://github.com/hakavlad .
  5. #
  6. # Example:
  7. #   ./notify_all_users.py earlyoom "Low memory! Killing/Terminating process 2233 tail"
  8. #
  9. # Notification that should pop up:
  10. #   earlyoom
  11. #   Low memory! Killing/Terminating process 2233 tail
  12.  
  13. from sys import argv
  14. from os import listdir
  15. from subprocess import Popen, TimeoutExpired
  16.  
  17. if argv[1] == "-h" or argv[1] == "--help":
  18.     print("Send a GUI notification to all logged-in users.")
  19.     print("")
  20.     print("Usage:")
  21.     print("  %s [OPTION?] <SUMMARY> [BODY]" % (argv[0]))
  22.     print("")
  23.     print("Application Options:")
  24.     print("  Same as notify-send, see `notify-send --help`.")
  25.     print("")
  26.     print("Examples:")
  27.     print("  %s mytitle mytext" % (argv[0]))
  28.     print("  %s -i dialog-warning earlyoom \"killing process X\"" % (argv[0]))
  29.     exit(1)
  30.  
  31. wait_time = 10
  32.  
  33. display_env = 'DISPLAY='
  34. dbus_env = 'DBUS_SESSION_BUS_ADDRESS='
  35. user_env = 'USER='
  36.  
  37.  
  38. def rline1(path):
  39.     """read 1st line from path."""
  40.     with open(path) as f:
  41.         for line in f:
  42.             return line
  43.  
  44.  
  45. def re_pid_environ(pid):
  46.     """
  47.    read environ of 1 process
  48.    returns tuple with USER, DBUS, DISPLAY like follow:
  49.    ('user', 'DISPLAY=:0',
  50.     'DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus')
  51.    returns None if these vars is not in /proc/[pid]/environ
  52.    """
  53.     try:
  54.         env = str(rline1('/proc/' + pid + '/environ'))
  55.         if display_env in env and dbus_env in env and user_env in env:
  56.             env_list = env.split('\x00')
  57.  
  58.             # iterating over a list of process environment variables
  59.             for i in env_list:
  60.                 if i.startswith(user_env):
  61.                     user = i
  62.                     continue
  63.  
  64.                 if i.startswith(display_env):
  65.                     display = i[:10]
  66.                     continue
  67.  
  68.                 if i.startswith(dbus_env):
  69.                     dbus = i
  70.                     continue
  71.  
  72.                 if i.startswith('HOME='):
  73.                     # exclude Display Manager's user
  74.                     if i.startswith('HOME=/var'):
  75.                         return None
  76.  
  77.             env = user.partition('USER=')[2], display, dbus
  78.             return env
  79.  
  80.     except FileNotFoundError:
  81.         return None
  82.     except ProcessLookupError:
  83.         return None
  84.  
  85.  
  86. def root_notify_env():
  87.     """return set(user, display, dbus)"""
  88.     unsorted_envs_list = []
  89.     # iterates over processes, find processes with suitable env
  90.     for pid in listdir('/proc'):
  91.         if pid[0].isdecimal() is False:
  92.             continue
  93.         one_env = re_pid_environ(pid)
  94.         unsorted_envs_list.append(one_env)
  95.     env = set(unsorted_envs_list)
  96.     env.discard(None)
  97.  
  98.     # deduplicate dbus
  99.     new_env = []
  100.     end = []
  101.     for i in env:
  102.         key = i[0] + i[1]
  103.         if key not in end:
  104.             end.append(key)
  105.             new_env.append(i)
  106.         else:
  107.             continue
  108.  
  109.     return new_env
  110.  
  111.  
  112. list_with_envs = root_notify_env()
  113.  
  114.  
  115. # if somebody logged in with GUI
  116. if len(list_with_envs) > 0:
  117.     # iterating over logged-in users
  118.     for i in list_with_envs:
  119.         username, display_env, dbus_env = i[0], i[1], i[2]
  120.         display_tuple = display_env.partition('=')
  121.         dbus_tuple = dbus_env.partition('=')
  122.         display_value = display_tuple[2]
  123.         dbus_value = dbus_tuple[2]
  124.  
  125.         with Popen([
  126.             'sudo', '-u', username,
  127.             'env',
  128.             'DISPLAY=' + display_value,
  129.             'DBUS_SESSION_BUS_ADDRESS=' + dbus_value,
  130.             'notify-send'] + argv[1:]
  131.         ) as proc:
  132.             try:
  133.                 proc.wait(timeout=wait_time)
  134.             except TimeoutExpired:
  135.                 proc.kill()
  136.                 print('TimeoutExpired: notify user:' + username)
  137. else:
  138.     print('Nobody logged-in with GUI. Nothing to do.')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement