From 6e197c1353c788109df07ee6d1242a5c2327e8f9 Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 1 Aug 2012 09:58:08 +0900 Subject: fileutil.which implementation --- src/leap/app.py | 2 +- src/leap/eip/conductor.py | 2 +- src/leap/util/__init__.py | 0 src/leap/util/coroutines.py | 107 ++++++++++++++++++++++++++++++++++++++++ src/leap/util/fileutil.py | 73 +++++++++++++++++++++++++++ src/leap/util/leap_argparse.py | 20 ++++++++ src/leap/utils/__init__.py | 0 src/leap/utils/coroutines.py | 107 ---------------------------------------- src/leap/utils/leap_argparse.py | 20 -------- 9 files changed, 202 insertions(+), 129 deletions(-) create mode 100644 src/leap/util/__init__.py create mode 100644 src/leap/util/coroutines.py create mode 100644 src/leap/util/fileutil.py create mode 100644 src/leap/util/leap_argparse.py delete mode 100644 src/leap/utils/__init__.py delete mode 100644 src/leap/utils/coroutines.py delete mode 100644 src/leap/utils/leap_argparse.py (limited to 'src/leap') diff --git a/src/leap/app.py b/src/leap/app.py index 0a61fd4f..186eb048 100644 --- a/src/leap/app.py +++ b/src/leap/app.py @@ -15,7 +15,7 @@ def main(): long live to the (hidden) leap window! """ import sys - from leap.utils import leap_argparse + from leap.util import leap_argparse parser, opts = leap_argparse.init_leapc_args() debug = getattr(opts, 'debug', False) diff --git a/src/leap/eip/conductor.py b/src/leap/eip/conductor.py index e3adadc4..3ce062aa 100644 --- a/src/leap/eip/conductor.py +++ b/src/leap/eip/conductor.py @@ -6,7 +6,7 @@ from __future__ import (division, unicode_literals, print_function) from functools import partial import logging -from leap.utils.coroutines import spawn_and_watch_process +from leap.util.coroutines import spawn_and_watch_process from leap.baseapp.config import get_config, get_vpn_stdout_mockup from leap.eip.vpnwatcher import EIPConnectionStatus, status_watcher from leap.eip.vpnmanager import OpenVPNManager, ConnectionRefusedError diff --git a/src/leap/util/__init__.py b/src/leap/util/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/leap/util/coroutines.py b/src/leap/util/coroutines.py new file mode 100644 index 00000000..5e25eb63 --- /dev/null +++ b/src/leap/util/coroutines.py @@ -0,0 +1,107 @@ +# the problem of watching a stdout pipe from +# openvpn binary: using subprocess and coroutines +# acting as event consumers + +from __future__ import division, print_function + +from subprocess import PIPE, Popen +import sys +from threading import Thread + +ON_POSIX = 'posix' in sys.builtin_module_names + + +# +# Coroutines goodies +# + +def coroutine(func): + def start(*args, **kwargs): + cr = func(*args, **kwargs) + cr.next() + return cr + return start + + +@coroutine +def process_events(callback): + """ + coroutine loop that receives + events sent and dispatch the callback. + :param callback: callback to be called\ +for each event + :type callback: callable + """ + try: + while True: + m = (yield) + if callable(callback): + callback(m) + else: + #XXX log instead + print('not a callable passed') + except GeneratorExit: + return + +# +# Threads +# + + +def launch_thread(target, args): + """ + launch and demonize thread. + :param target: target function that will run in thread + :type target: function + :param args: args to be passed to thread + :type args: list + """ + t = Thread(target=target, + args=args) + t.daemon = True + t.start() + return t + + +def watch_output(out, observers): + """ + initializes dict of observer coroutines + and pushes lines to each of them as they are received + from the watched output. + :param out: stdout of a process. + :type out: fd + :param observers: tuple of coroutines to send data\ +for each event + :type ovservers: tuple + """ + observer_dict = {observer: process_events(observer) + for observer in observers} + for line in iter(out.readline, b''): + for obs in observer_dict: + observer_dict[obs].send(line) + out.close() + + +def spawn_and_watch_process(command, args, observers=None): + """ + spawns a subprocess with command, args, and launch + a watcher thread. + :param command: command to be executed in the subprocess + :type command: str + :param args: arguments + :type args: list + :param observers: tuple of observer functions to be called \ +for each line in the subprocess output. + :type observers: tuple + :return: a tuple containing the child process instance, and watcher_thread, + :rtype: (Subprocess, Thread) + """ + subp = Popen([command] + args, + stdout=PIPE, + stderr=PIPE, + bufsize=1, + close_fds=ON_POSIX) + watcher = launch_thread( + watch_output, + (subp.stdout, observers)) + return subp, watcher diff --git a/src/leap/util/fileutil.py b/src/leap/util/fileutil.py new file mode 100644 index 00000000..86a44a89 --- /dev/null +++ b/src/leap/util/fileutil.py @@ -0,0 +1,73 @@ +from itertools import chain +import os +import platform +import stat + + +def is_user_executable(fpath): + st = os.stat(fpath) + return bool(st.st_mode & stat.S_IXUSR) + + +def extend_path(): + ourplatform = platform.system() + if ourplatform == "Linux": + return "/usr/local/sbin:/usr/sbin" + # XXX add mac / win extended search paths? + + +def which(program): + """ + an implementation of which + that extends the path with + other locations, like sbin + (f.i., openvpn binary is likely to be there) + @param program: a string representing the binary we're looking for. + """ + def is_exe(fpath): + """ + check that path exists, + it's a file, + and is executable by the owner + """ + # we would check for access, + # but it's likely that we're + # using uid 0 + polkitd + + return os.path.isfile(fpath)\ + and is_user_executable(fpath) + + def ext_candidates(fpath): + yield fpath + for ext in os.environ.get("PATHEXT", "").split(os.pathsep): + yield fpath + ext + + def iter_path(pathset): + """ + returns iterator with + full path for a given path list + and the current target bin. + """ + for path in pathset.split(os.pathsep): + exe_file = os.path.join(path, program) + #print 'file=%s' % exe_file + for candidate in ext_candidates(exe_file): + if is_exe(candidate): + yield candidate + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + # extended iterator + # with extra path + extended_path = chain( + iter_path(os.environ["PATH"]), + iter_path(extend_path())) + for candidate in extended_path: + if candidate is not None: + return candidate + + # sorry bro. + return None diff --git a/src/leap/util/leap_argparse.py b/src/leap/util/leap_argparse.py new file mode 100644 index 00000000..9c355134 --- /dev/null +++ b/src/leap/util/leap_argparse.py @@ -0,0 +1,20 @@ +import argparse + + +def build_parser(): + epilog = "Copyright 2012 The Leap Project" + parser = argparse.ArgumentParser(description=""" +Launches main LEAP Client""", epilog=epilog) + parser.add_argument('--debug', action="store_true", + help='launches in debug mode') + parser.add_argument('--config', metavar="CONFIG FILE", nargs='?', + action="store", dest="config_file", + type=argparse.FileType('r'), + help='optional config file') + return parser + + +def init_leapc_args(): + parser = build_parser() + opts = parser.parse_args() + return parser, opts diff --git a/src/leap/utils/__init__.py b/src/leap/utils/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/leap/utils/coroutines.py b/src/leap/utils/coroutines.py deleted file mode 100644 index 5e25eb63..00000000 --- a/src/leap/utils/coroutines.py +++ /dev/null @@ -1,107 +0,0 @@ -# the problem of watching a stdout pipe from -# openvpn binary: using subprocess and coroutines -# acting as event consumers - -from __future__ import division, print_function - -from subprocess import PIPE, Popen -import sys -from threading import Thread - -ON_POSIX = 'posix' in sys.builtin_module_names - - -# -# Coroutines goodies -# - -def coroutine(func): - def start(*args, **kwargs): - cr = func(*args, **kwargs) - cr.next() - return cr - return start - - -@coroutine -def process_events(callback): - """ - coroutine loop that receives - events sent and dispatch the callback. - :param callback: callback to be called\ -for each event - :type callback: callable - """ - try: - while True: - m = (yield) - if callable(callback): - callback(m) - else: - #XXX log instead - print('not a callable passed') - except GeneratorExit: - return - -# -# Threads -# - - -def launch_thread(target, args): - """ - launch and demonize thread. - :param target: target function that will run in thread - :type target: function - :param args: args to be passed to thread - :type args: list - """ - t = Thread(target=target, - args=args) - t.daemon = True - t.start() - return t - - -def watch_output(out, observers): - """ - initializes dict of observer coroutines - and pushes lines to each of them as they are received - from the watched output. - :param out: stdout of a process. - :type out: fd - :param observers: tuple of coroutines to send data\ -for each event - :type ovservers: tuple - """ - observer_dict = {observer: process_events(observer) - for observer in observers} - for line in iter(out.readline, b''): - for obs in observer_dict: - observer_dict[obs].send(line) - out.close() - - -def spawn_and_watch_process(command, args, observers=None): - """ - spawns a subprocess with command, args, and launch - a watcher thread. - :param command: command to be executed in the subprocess - :type command: str - :param args: arguments - :type args: list - :param observers: tuple of observer functions to be called \ -for each line in the subprocess output. - :type observers: tuple - :return: a tuple containing the child process instance, and watcher_thread, - :rtype: (Subprocess, Thread) - """ - subp = Popen([command] + args, - stdout=PIPE, - stderr=PIPE, - bufsize=1, - close_fds=ON_POSIX) - watcher = launch_thread( - watch_output, - (subp.stdout, observers)) - return subp, watcher diff --git a/src/leap/utils/leap_argparse.py b/src/leap/utils/leap_argparse.py deleted file mode 100644 index 9c355134..00000000 --- a/src/leap/utils/leap_argparse.py +++ /dev/null @@ -1,20 +0,0 @@ -import argparse - - -def build_parser(): - epilog = "Copyright 2012 The Leap Project" - parser = argparse.ArgumentParser(description=""" -Launches main LEAP Client""", epilog=epilog) - parser.add_argument('--debug', action="store_true", - help='launches in debug mode') - parser.add_argument('--config', metavar="CONFIG FILE", nargs='?', - action="store", dest="config_file", - type=argparse.FileType('r'), - help='optional config file') - return parser - - -def init_leapc_args(): - parser = build_parser() - opts = parser.parse_args() - return parser, opts -- cgit v1.2.3