Source code for libdesktop.startup

# coding: utf-8

# This file is part of libdesktop

# The MIT License (MIT)
#
# Copyright (c) 2016 Bharadwaj Raju
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


import os
import sys
import plistlib
import subprocess as sp
import shutil
from libdesktop import system
from libdesktop import desktopfile
from libdesktop import applications
from libdesktop import directories

[docs]def add_item(name, command, system_wide=False): '''Adds a program to startup. Adds a program to user startup. Args: name (str) : The name of the startup entry. command (str) : The command to run. system_wide (bool): Add to system-wide startup. Note: ``system_wide`` requires superuser/admin privileges. ''' desktop_env = system.get_name() if os.path.isfile(command): command_is_file = True if not desktop_env == 'windows': # Will not exit program if insufficient permissions sp.Popen(['chmod +x %s' % command], shell=True) if desktop_env == 'windows': import winreg if system_wide: startup_dir = os.path.join(winreg.ExpandEnvironmentStrings('%PROGRAMDATA%'), 'Microsoft\\Windows\\Start Menu\\Programs\\Startup') else: startup_dir = os.path.join(get_config_dir()[0], 'Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup') if not command_is_file: with open(os.path.join(startup_dir, name + '.bat'), 'w') as f: f.write(command) else: shutil.copy(command, startup_dir) elif desktop_env == 'mac': sp.Popen(['launchctl submit -l %s -- %s'] % (name, command), shell=True) # system-wide will be handled by running the above as root # which will auto-happen if current process is root. else: # Linux/Unix if desktop_env == 'unknown': # CLI if system_wide: login_file = '/etc/profile' else: login_file = os.path.expanduser('~/.profile') with open(login_file, 'a') as f: f.write(command) else: try: desktop_file_name = name + '.desktop' startup_file = os.path.join(get_config_dir('autostart', system_wide=system_wide)[0], desktop_file_name) # .desktop files' Terminal option uses an independent method to find terminal emulator desktop_str = desktopfile.construct(name=name, exec_=command, additional_opts={'X-GNOME-Autostart-enabled': 'true'}) with open(startup_file, 'w') as f: f.write(desktop_str) except: pass
[docs]def list_items(system_wide=False): '''List startup programs. List the programs set to run at startup. Args: system_wide (bool): Gets the programs that run at system-wide startup. Returns: list: A list of dictionaries in this format: .. code-block:: python { 'name': 'The name of the entry.', 'command': 'The command used to run it.' } ''' desktop_env = system.get_name() result = [] if desktop_env == 'windows': sys_startup_dir = os.path.join(winreg.ExpandEnvironmentStrings('%PROGRAMDATA%'), 'Microsoft\\Windows\\Start Menu\\Programs\\Startup') user_startup_dir = os.path.join(get_config_dir()[0], 'Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup') startup_dir = sys_startup_dir if system_wide else user_startup_dir for file in os.listdir(startup_dir): file_path = os.path.join(startup_dir, file) result.append({ 'name': file, 'command': os.path.join(startup_dir, file) }) elif desktop_env == 'mac': items_list = system.get_cmd_out('launchtl list | awk \'{print $3}\'') for item in items_list.split('\n'): # launchd stores each job as a .plist file (pseudo-xml) launchd_plist_paths = ['~/Library/LaunchAgents', '/Library/LaunchAgents', '/Library/LaunchDaemons', '/System/Library/LaunchAgents', '/System/Library/LaunchDaemons'] for path in launchd_plist_paths: if item + '.plist' in os.listdir(path): plist_file = os.path.join(path, item + '.plist') # Parse the plist if sys.version_info.major == 2: plist_parsed = plistlib.readPlist(plist_file) else: with open(plist_file) as f: plist_parsed = plistlib.load(f) if 'Program' in plist_parsed: cmd = plist_parsed['Program'] if 'ProgramArguments' in plist_parsed: cmd += ' '.join(plist_parsed['ProgramArguments']) elif 'ProgramArguments' in plist_parsed: cmd = ' '.join(plist_parsed['ProgramArguments']) else: cmd = '' result.append({ 'name': item, 'command': cmd }) # system-wide will be handled by running the above as root # which will auto-happen if current process is root. else: # Linux/Unix # CLI profile = os.path.expanduser('~/.profile') if os.path.isfile(profile): with open(profile) as f: for line in f: if system.is_in_path(line.lstrip().split(' ')[0]): cmd_name = line.lstrip().split(' ')[0] result.append({ 'name': cmd_name, 'command': line.strip() }) # /etc/profile.d if system_wide: if os.path.isdir('/etc/profile.d'): for file in os.listdir('/etc/profile.d'): file_path = os.path.join('/etc/profile.d', file) result.append({ 'name': file, 'command': 'sh %s' % file_path }) # GUI try: startup_dir = directories.get_config_dir('autostart', system_wide=system_wide)[0] for file in os.listdir(startup_dir): file_parsed = desktopfile.parse(os.path.join(startup_dir, file)) if 'Name' in file_parsed: name = file_parsed['Name'] else: name = file.replace('.desktop', '') if 'Exec' in file_parsed: if file_parsed['Terminal']: cmd = applications.terminal(exec_=file_parsed['Exec'], return_cmd=True) else: cmd = file_parsed['Exec'] else: cmd = '' if not file_parsed.get('Hidden', False): result.append({ 'name': name, 'command': cmd }) except IndexError: pass return result
[docs]def remove_item(name, system_wide=False): '''Removes a program from startup. Removes a program from startup. Args: name (str) : The name of the program (as known to the system) to remove. See :func:``list_items``. system_wide (bool): Remove it from system-wide startup. Note: ``system_wide`` requires superuser/admin privileges. ''' desktop_env = system.get_name() if desktop_env == 'windows': import winreg if system_wide: startup_dir = os.path.join(winreg.ExpandEnvironmentStrings('%PROGRAMDATA%'), 'Microsoft\\Windows\\Start Menu\\Programs\\Startup') else: startup_dir = os.path.join(directories.get_config_dir()[0], 'Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup') for startup_file in os.path.listdir(start_dir): if startup_file == name or startup_file.split('.')[0] == name: os.remove(os.path.join(startup_dir, startup_file)) elif desktop_env == 'mac': sp.Popen(['launchctl', 'remove', name]) # system-wide will be handled by running the above as root # which will auto-happen if current process is root. else: # Linux/Unix if desktop_env == 'unknown': # CLI if system_wide: login_file = '/etc/profile' else: login_file = os.path.expanduser('~/.profile') with open(login_file) as f: login_file_contents = f.read() final_login_file_contents = '' for line in login_file_contents.split('\n'): if line.split(' ')[0] != name: final_login_file_contents += line with open(login_file, 'w') as f: f.write(final_login_file_contents) else: try: desktop_file_name = name + '.desktop' startup_file = os.path.join(directories.get_config_dir('autostart', system_wide=system_wide)[0], desktop_file_name) if not os.path.isfile(startup_file): for possible_startup_file in os.listdir(directories.get_config_dir('autostart', system_wide=system_wide)[0]): possible_startup_file_parsed = desktopfile.parse(possible_startup_file) if possible_startup_file_parsed['Name'] == name: startup_file = possible_startup_file os.remove(startup_file) except IndexError: pass