def _get_user_processes(): """ Gets process information owned by the current user. Returns generator of tuples: (``psutil.Process`` instance, path). """ uid = os.getuid() for proc in psutil.process_iter(): try: # yield processes that match current user if proc.uids.real == uid: yield (proc, proc.exe) except psutil.AccessDenied: # work around for suid/sguid processes and MacOS X restrictions try: path = common.which(proc.name) # psutil doesn't support MacOS X relative paths, # let's use a workaround to merge working directory with # process relative path if not path and common.IS_MACOSX: cwd = _get_process_cwd(proc.pid) if not cwd: continue path = os.path.join(cwd, proc.cmdline[0]) yield (proc, path) except (psutil.AccessDenied, OSError): pass except psutil.NoSuchProcess: pass
def _play_sound(self, filename): """ Shells player with the provided filename. `filename` Filename for sound file. """ command = self._get_external_player() if not command: return # no player found if common.IS_MACOSX: command += ' "{0}"'.format(filename) else: # append quiet flag and filename is_play = (command == 'play') command += ' -q "{0}"'.format(filename) # HACK: play can default to using pulseaudio. here, we # check if pulse command exists and delegate to alsa if # not if is_play and not common.which('pulseaudio'): command += ' -t alsa' # play sound file, ignore if it fails common.shell_process(command, background=True)
def _get_external_player(self): """ Determines external sound player to available. Returns string or ``None``. """ if common.IS_MACOSX: return 'afplay' else: for name in ('mpg123', 'play', 'aplay'): if common.which(name): return name return None # couldn't find a player
def testReturnPathNonExecOrDir__which(self): """ common.which: returns ``None`` if value is a path and it's a directory or non-executable file. """ self.assertIsNone(common.which('/bin')) self.assertIsNone(common.which('/etc/hosts'))
def testReturnPath__which(self): """ common.which: returns same value if path is given. """ self.assertEqual(common.which('/bin/cat'), '/bin/cat')
def testNotExistCommand__which(self): """ common.which: returns ``None`` for non-existent commands. """ self.assertIsNone(common.which('this-is-fake-command'))
def testExistCommand__which(self): """ common.which: returns full path for existing commands. """ self.assertEqual(common.which('cat'), '/bin/cat') self.assertEqual(common.which('ls'), '/bin/ls') self.assertEqual(common.which('rm'), '/bin/rm')
def _handle_block(self, task, disable=False): """ Handles blocking domains using hosts file. `task` ``Task`` instance. `disable` Set to ``True``, to turn off blocking and restore hosts file; otherwise, ``False`` will enable blocking by updating hosts file. Returns boolean. """ backup_file = os.path.join(task.task_dir, '.hosts.bak') self.orig_data = self.orig_data or common.readfile(backup_file) self.last_updated = self.last_updated or -1 if not self.orig_data: # should't attempt restore without good original data, bail if disable: return False # attempt to fetch data from the source self.orig_data = common.readfile(self.hosts_file) if not self.orig_data: return False # restore backup if not os.path.exists(backup_file): common.writefile(backup_file, self.orig_data) # bail early if hosts file modification time hasn't changed try: should_write = (disable or self.last_updated != os.path.getmtime(self.hosts_file)) except OSError: should_write = True # file was removed, let's write! if not should_write: return True # make copy of original data, in case we need to modify data = self.orig_data # if not restoring, tack on domains mapped # to localhost to end of file data if not disable: # convert the set to a list and sort domains = list(self.domains) domains.sort() data += ('\n'.join('127.0.0.1\t{0}\t# FOCUS' .format(d) for d in domains) + '\n') # make temp file with new host file data with tempfile.NamedTemporaryFile(prefix='focus_') as tempf: tempf.write(data) tempf.flush() # overwrite hosts file with our modified copy. if not self.run_root('cp "{0}" "{1}"'.format(tempf.name, self.hosts_file)): return False # MacOS X generally requires flushing the system dns cache to pick # up changes to the hosts file: # dscacheutil -flushcache or lookupd -flushcache if common.IS_MACOSX: dscacheutil, lookupd = [common.which(x) for x in ('dscacheutil', 'lookupd')] self.run_root(' '.join([dscacheutil or lookupd, '-flushcache'])) if disable: common.safe_remove_file(backup_file) # cleanup the backup # store last modification time try: self.last_updated = os.path.getmtime(self.hosts_file) except OSError: # file was removed, let's update next time around self.last_updated = -1 return True
def _handle_block(self, task, disable=False): """ Handles blocking domains using hosts file. `task` ``Task`` instance. `disable` Set to ``True``, to turn off blocking and restore hosts file; otherwise, ``False`` will enable blocking by updating hosts file. Returns boolean. """ backup_file = os.path.join(task.task_dir, '.hosts.bak') self.orig_data = self.orig_data or common.readfile(backup_file) self.last_updated = self.last_updated or -1 if not self.orig_data: # should't attempt restore without good original data, bail if disable: return False # attempt to fetch data from the source self.orig_data = common.readfile(self.hosts_file) if not self.orig_data: return False # restore backup if not os.path.exists(backup_file): common.writefile(backup_file, self.orig_data) # bail early if hosts file modification time hasn't changed try: should_write = ( disable or self.last_updated != os.path.getmtime(self.hosts_file)) except OSError: should_write = True # file was removed, let's write! if not should_write: return True # make copy of original data, in case we need to modify data = self.orig_data # if not restoring, tack on domains mapped # to localhost to end of file data if not disable: # convert the set to a list and sort domains = list(self.domains) domains.sort() data += ('\n'.join('127.0.0.1\t{0}\t# FOCUS'.format(d) for d in domains) + '\n') # make temp file with new host file data with tempfile.NamedTemporaryFile(prefix='focus_') as tempf: tempf.write(data) tempf.flush() # overwrite hosts file with our modified copy. if not self.run_root('cp "{0}" "{1}"'.format( tempf.name, self.hosts_file)): return False # MacOS X generally requires flushing the system dns cache to pick # up changes to the hosts file: # dscacheutil -flushcache or lookupd -flushcache if common.IS_MACOSX: dscacheutil, lookupd = [ common.which(x) for x in ('dscacheutil', 'lookupd') ] self.run_root(' '.join([dscacheutil or lookupd, '-flushcache'])) if disable: common.safe_remove_file(backup_file) # cleanup the backup # store last modification time try: self.last_updated = os.path.getmtime(self.hosts_file) except OSError: # file was removed, let's update next time around self.last_updated = -1 return True