From 83de7942237b8294df47f318133fc5d7c260d496 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Thu, 12 Sep 2013 16:30:43 +0200 Subject: Add original buildserver from @fraca7 --- devscripts/buildserver.py | 272 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 devscripts/buildserver.py (limited to 'devscripts/buildserver.py') diff --git a/devscripts/buildserver.py b/devscripts/buildserver.py new file mode 100644 index 000000000..4fe80edce --- /dev/null +++ b/devscripts/buildserver.py @@ -0,0 +1,272 @@ +#!/usr/bin/python + +## This is free and unencumbered software released into the public domain. + +## Anyone is free to copy, modify, publish, use, compile, sell, or +## distribute this software, either in source code form or as a compiled +## binary, for any purpose, commercial or non-commercial, and by any +## means. + +## In jurisdictions that recognize copyright laws, the author or authors +## of this software dedicate any and all copyright interest in the +## software to the public domain. We make this dedication for the benefit +## of the public at large and to the detriment of our heirs and +## successors. We intend this dedication to be an overt act of +## relinquishment in perpetuity of all present and future rights to this +## software under copyright law. + +## 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 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. + +## For more information, please refer to + +from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler +from SocketServer import ThreadingMixIn +import getopt, threading, sys, urlparse, _winreg, os, subprocess, shutil, tempfile + + +class BuildHTTPServer(ThreadingMixIn, HTTPServer): + allow_reuse_address = True + + +def usage(): + print 'Usage: %s [options]' + print 'Options:' + print + print ' -h, --help Display this help' + print ' -i, --install Launch at session startup' + print ' -u, --uninstall Do not launch at session startup' + print ' -b, --bind Bind to host:port (default localhost:8142)' + sys.exit(0) + + +def main(argv): + opts, args = getopt.getopt(argv, 'hb:iu', ['help', 'bind=', 'install', 'uninstall']) + host = 'localhost' + port = 8142 + + for opt, val in opts: + if opt in ['-h', '--help']: + usage() + elif opt in ['-b', '--bind']: + try: + host, port = val.split(':') + except ValueError: + host = val + else: + port = int(port) + elif opt in ['-i', '--install']: + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, _winreg.KEY_WRITE) + try: + _winreg.SetValueEx(key, 'Youtube-dl builder', 0, _winreg.REG_SZ, + '"%s" "%s" -b %s:%d' % (sys.executable, os.path.normpath(os.path.abspath(sys.argv[0])), + host, port)) + finally: + _winreg.CloseKey(key) + print 'Installed.' + sys.exit(0) + elif opt in ['-u', '--uninstall']: + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, _winreg.KEY_WRITE) + try: + _winreg.DeleteValue(key, 'Youtube-dl builder') + finally: + _winreg.CloseKey(key) + print 'Uninstalled.' + sys.exit(0) + + print 'Listening on %s:%d' % (host, port) + srv = BuildHTTPServer((host, port), BuildHTTPRequestHandler) + thr = threading.Thread(target=srv.serve_forever) + thr.start() + raw_input('Hit to stop...\n') + srv.shutdown() + thr.join() + + +def rmtree(path): + for name in os.listdir(path): + fname = os.path.join(path, name) + if os.path.isdir(fname): + rmtree(fname) + else: + os.chmod(fname, 0666) + os.remove(fname) + os.rmdir(path) + +#============================================================================== + +class BuildError(Exception): + def __init__(self, output, code=500): + self.output = output + self.code = code + + def __str__(self): + return self.output + + +class HTTPError(BuildError): + pass + + +class PythonBuilder(object): + def __init__(self, **kwargs): + pythonVersion = kwargs.pop('python', '2.7') + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Python\PythonCore\%s\InstallPath' % pythonVersion) + try: + self.pythonPath, _ = _winreg.QueryValueEx(key, '') + finally: + _winreg.CloseKey(key) + except Exception: + raise BuildError('No such Python version: %s' % pythonVersion) + + super(PythonBuilder, self).__init__(**kwargs) + + +class GITInfoBuilder(object): + def __init__(self, **kwargs): + try: + self.user, self.repoName = kwargs['path'][:2] + self.rev = kwargs.pop('rev') + except ValueError: + raise BuildError('Invalid path') + except KeyError as e: + raise BuildError('Missing mandatory parameter "%s"' % e.args[0]) + + path = os.path.join(os.environ['APPDATA'], 'Build archive', self.repoName, self.user) + if not os.path.exists(path): + os.makedirs(path) + self.basePath = tempfile.mkdtemp(dir=path) + self.buildPath = os.path.join(self.basePath, 'build') + + super(GITInfoBuilder, self).__init__(**kwargs) + + +class GITBuilder(GITInfoBuilder): + def build(self): + try: + subprocess.check_output(['git', 'clone', 'git://github.com/%s/%s.git' % (self.user, self.repoName), self.buildPath]) + subprocess.check_output(['git', 'checkout', self.rev], cwd=self.buildPath) + except subprocess.CalledProcessError as e: + raise BuildError(e.output) + + super(GITBuilder, self).build() + + +class YoutubeDLBuilder(object): + authorizedUsers = ['fraca7', 'phihag', 'rg3', 'FiloSottile'] + + def __init__(self, **kwargs): + if self.repoName != 'youtube-dl': + raise BuildError('Invalid repository "%s"' % self.repoName) + if self.user not in self.authorizedUsers: + raise HTTPError('Unauthorized user "%s"' % self.user, 401) + + super(YoutubeDLBuilder, self).__init__(**kwargs) + + def build(self): + try: + subprocess.check_output([os.path.join(self.pythonPath, 'python.exe'), 'setup.py', 'py2exe'], + cwd=self.buildPath) + except subprocess.CalledProcessError as e: + raise BuildError(e.output) + + super(YoutubeDLBuilder, self).build() + + +class DownloadBuilder(object): + def __init__(self, **kwargs): + self.handler = kwargs.pop('handler') + self.srcPath = os.path.join(self.buildPath, *tuple(kwargs['path'][2:])) + self.srcPath = os.path.abspath(os.path.normpath(self.srcPath)) + if not self.srcPath.startswith(self.buildPath): + raise HTTPError(self.srcPath, 401) + + super(DownloadBuilder, self).__init__(**kwargs) + + def build(self): + if not os.path.exists(self.srcPath): + raise HTTPError('No such file', 404) + if os.path.isdir(self.srcPath): + raise HTTPError('Is a directory: %s' % self.srcPath, 401) + + self.handler.send_response(200) + self.handler.send_header('Content-Type', 'application/octet-stream') + self.handler.send_header('Content-Disposition', 'attachment; filename=%s' % os.path.split(self.srcPath)[-1]) + self.handler.send_header('Content-Length', str(os.stat(self.srcPath).st_size)) + self.handler.end_headers() + + with open(self.srcPath, 'rb') as src: + shutil.copyfileobj(src, self.handler.wfile) + + super(DownloadBuilder, self).build() + + +class CleanupTempDir(object): + def build(self): + try: + rmtree(self.basePath) + except Exception as e: + print 'WARNING deleting "%s": %s' % (self.basePath, e) + + super(CleanupTempDir, self).build() + + +class Null(object): + def __init__(self, **kwargs): + pass + + def start(self): + pass + + def close(self): + pass + + def build(self): + pass + + +class Builder(PythonBuilder, GITBuilder, YoutubeDLBuilder, DownloadBuilder, CleanupTempDir, Null): + pass + + +class BuildHTTPRequestHandler(BaseHTTPRequestHandler): + actionDict = { 'build': Builder, 'download': Builder } # They're the same, no more caching. + + def do_GET(self): + path = urlparse.urlparse(self.path) + paramDict = dict([(key, value[0]) for key, value in urlparse.parse_qs(path.query).items()]) + action, _, path = path.path.strip('/').partition('/') + if path: + path = path.split('/') + if action in self.actionDict: + try: + builder = self.actionDict[action](path=path, handler=self, **paramDict) + builder.start() + try: + builder.build() + finally: + builder.close() + except BuildError as e: + self.send_response(e.code) + msg = unicode(e).encode('UTF-8') + self.send_header('Content-Type', 'text/plain; charset=UTF-8') + self.send_header('Content-Length', len(msg)) + self.end_headers() + self.wfile.write(msg) + except HTTPError as e: + self.send_response(e.code, str(e)) + else: + self.send_response(500, 'Unknown build method "%s"' % action) + else: + self.send_response(500, 'Malformed URL') + +#============================================================================== + +if __name__ == '__main__': + main(sys.argv[1:]) -- cgit v1.2.3 From 353ba14060528d981213c66131bc770f478935de Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Thu, 12 Sep 2013 16:34:24 +0200 Subject: [buildserver] Rely on repository license --- devscripts/buildserver.py | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'devscripts/buildserver.py') diff --git a/devscripts/buildserver.py b/devscripts/buildserver.py index 4fe80edce..edc437dee 100644 --- a/devscripts/buildserver.py +++ b/devscripts/buildserver.py @@ -1,30 +1,5 @@ #!/usr/bin/python -## This is free and unencumbered software released into the public domain. - -## Anyone is free to copy, modify, publish, use, compile, sell, or -## distribute this software, either in source code form or as a compiled -## binary, for any purpose, commercial or non-commercial, and by any -## means. - -## In jurisdictions that recognize copyright laws, the author or authors -## of this software dedicate any and all copyright interest in the -## software to the public domain. We make this dedication for the benefit -## of the public at large and to the detriment of our heirs and -## successors. We intend this dedication to be an overt act of -## relinquishment in perpetuity of all present and future rights to this -## software under copyright law. - -## 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 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. - -## For more information, please refer to - from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler from SocketServer import ThreadingMixIn import getopt, threading, sys, urlparse, _winreg, os, subprocess, shutil, tempfile -- cgit v1.2.3 From 71cedb3c0c6860c1cf06792a8e98940f88b34a17 Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Fri, 13 Sep 2013 02:25:12 +0200 Subject: [buildserver] Service installation and uninstallation --- devscripts/buildserver.py | 145 ++++++++++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 50 deletions(-) (limited to 'devscripts/buildserver.py') diff --git a/devscripts/buildserver.py b/devscripts/buildserver.py index edc437dee..45c875b23 100644 --- a/devscripts/buildserver.py +++ b/devscripts/buildserver.py @@ -1,64 +1,109 @@ -#!/usr/bin/python +#!/usr/bin/python3 -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from SocketServer import ThreadingMixIn -import getopt, threading, sys, urlparse, _winreg, os, subprocess, shutil, tempfile +from http.server import HTTPServer, BaseHTTPRequestHandler +from socketserver import ThreadingMixIn +import argparse +import ctypes +import sys +import threading +import os.path class BuildHTTPServer(ThreadingMixIn, HTTPServer): allow_reuse_address = True -def usage(): - print 'Usage: %s [options]' - print 'Options:' - print - print ' -h, --help Display this help' - print ' -i, --install Launch at session startup' - print ' -u, --uninstall Do not launch at session startup' - print ' -b, --bind Bind to host:port (default localhost:8142)' - sys.exit(0) +advapi32 = ctypes.windll.advapi32 +SC_MANAGER_ALL_ACCESS = 0xf003f +SC_MANAGER_CREATE_SERVICE = 0x02 +SERVICE_WIN32_OWN_PROCESS = 0x10 +SERVICE_AUTO_START = 0x2 +SERVICE_ERROR_NORMAL = 0x1 +DELETE = 0x00010000 -def main(argv): - opts, args = getopt.getopt(argv, 'hb:iu', ['help', 'bind=', 'install', 'uninstall']) - host = 'localhost' - port = 8142 - - for opt, val in opts: - if opt in ['-h', '--help']: - usage() - elif opt in ['-b', '--bind']: - try: - host, port = val.split(':') - except ValueError: - host = val - else: - port = int(port) - elif opt in ['-i', '--install']: - key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, _winreg.KEY_WRITE) - try: - _winreg.SetValueEx(key, 'Youtube-dl builder', 0, _winreg.REG_SZ, - '"%s" "%s" -b %s:%d' % (sys.executable, os.path.normpath(os.path.abspath(sys.argv[0])), - host, port)) - finally: - _winreg.CloseKey(key) - print 'Installed.' - sys.exit(0) - elif opt in ['-u', '--uninstall']: - key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, _winreg.KEY_WRITE) - try: - _winreg.DeleteValue(key, 'Youtube-dl builder') - finally: - _winreg.CloseKey(key) - print 'Uninstalled.' - sys.exit(0) - print 'Listening on %s:%d' % (host, port) +def win_OpenSCManager(): + res = advapi32.OpenSCManagerA(None, None, SC_MANAGER_ALL_ACCESS) + if not res: + raise Exception('Opening service manager failed - ' + 'are you running this as administrator?') + return res + + +def win_install_service(service_name, cmdline): + manager = win_OpenSCManager() + try: + h = advapi32.CreateServiceA( + manager, service_name, None, + SC_MANAGER_CREATE_SERVICE, SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, + cmdline, None, None, None, None, None) + if not h: + raise OSError('Service creation failed: %s' % ctypes.FormatError()) + + advapi32.CloseServiceHandle(h) + finally: + advapi32.CloseServiceHandle(manager) + + +def win_uninstall_service(service_name): + manager = win_OpenSCManager() + try: + h = advapi32.OpenServiceA(manager, service_name, DELETE) + if not h: + raise OSError('Could not find service %s: %s' % ( + service_name, ctypes.FormatError())) + + try: + if not advapi32.DeleteService(h): + raise OSError('Deletion failed: %s' % ctypes.FormatError()) + finally: + advapi32.CloseServiceHandle(h) + finally: + advapi32.CloseServiceHandle(manager) + + +def install_service(bind): + fn = os.path.normpath(__file__) + cmdline = '"%s" "%s" -s -b "%s"' % (sys.executable, fn, bind) + win_install_service('youtubedl_builder', cmdline) + + +def uninstall_service(): + win_uninstall_service('youtubedl_builder') + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument('-i', '--install', + action='store_const', dest='action', const='install', + help='Launch at Windows startup') + parser.add_argument('-u', '--uninstall', + action='store_const', dest='action', const='uninstall', + help='Remove Windows service') + parser.add_argument('-s', '--service', + action='store_const', dest='action', const='servce', + help='Run as a Windows service') + parser.add_argument('-b', '--bind', metavar='', + action='store', default='localhost:8142', + help='Bind to host:port (default %default)') + options = parser.parse_args() + + if options.action == 'install': + return install_service(options.bind) + + if options.action == 'uninstall': + return uninstall_service() + + host, port_str = options.bind.split(':') + port = int(port_str) + + print('Listening on %s:%d' % (host, port)) srv = BuildHTTPServer((host, port), BuildHTTPRequestHandler) thr = threading.Thread(target=srv.serve_forever) thr.start() - raw_input('Hit to stop...\n') + input('Press ENTER to shut down') srv.shutdown() thr.join() @@ -69,7 +114,7 @@ def rmtree(path): if os.path.isdir(fname): rmtree(fname) else: - os.chmod(fname, 0666) + os.chmod(fname, 0o666) os.remove(fname) os.rmdir(path) @@ -187,7 +232,7 @@ class CleanupTempDir(object): try: rmtree(self.basePath) except Exception as e: - print 'WARNING deleting "%s": %s' % (self.basePath, e) + print('WARNING deleting "%s": %s' % (self.basePath, e)) super(CleanupTempDir, self).build() -- cgit v1.2.3 From 22b50ecb2f7f9e0469d281a4c401d4a531c1cc5b Mon Sep 17 00:00:00 2001 From: Philipp Hagemeister Date: Mon, 16 Sep 2013 03:32:45 +0200 Subject: Starts of a Windows service --- devscripts/buildserver.py | 143 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 15 deletions(-) (limited to 'devscripts/buildserver.py') diff --git a/devscripts/buildserver.py b/devscripts/buildserver.py index 45c875b23..e0c3cc83e 100644 --- a/devscripts/buildserver.py +++ b/devscripts/buildserver.py @@ -4,8 +4,10 @@ from http.server import HTTPServer, BaseHTTPRequestHandler from socketserver import ThreadingMixIn import argparse import ctypes +import functools import sys import threading +import traceback import os.path @@ -21,10 +23,40 @@ SERVICE_WIN32_OWN_PROCESS = 0x10 SERVICE_AUTO_START = 0x2 SERVICE_ERROR_NORMAL = 0x1 DELETE = 0x00010000 +SERVICE_STATUS_START_PENDING = 0x00000002 +SERVICE_STATUS_RUNNING = 0x00000004 +SERVICE_ACCEPT_STOP = 0x1 + +SVCNAME = 'youtubedl_builder' + +LPTSTR = ctypes.c_wchar_p +START_CALLBACK = ctypes.WINFUNCTYPE(None, ctypes.c_int, ctypes.POINTER(LPTSTR)) + + +class SERVICE_TABLE_ENTRY(ctypes.Structure): + _fields_ = [ + ('lpServiceName', LPTSTR), + ('lpServiceProc', START_CALLBACK) + ] + + +HandlerEx = ctypes.WINFUNCTYPE( + ctypes.c_int, # return + ctypes.c_int, # dwControl + ctypes.c_int, # dwEventType + ctypes.c_void_p, # lpEventData, + ctypes.c_void_p, # lpContext, +) + + +def _ctypes_array(c_type, py_array): + ar = (c_type * len(py_array))() + ar[:] = py_array + return ar def win_OpenSCManager(): - res = advapi32.OpenSCManagerA(None, None, SC_MANAGER_ALL_ACCESS) + res = advapi32.OpenSCManagerW(None, None, SC_MANAGER_ALL_ACCESS) if not res: raise Exception('Opening service manager failed - ' 'are you running this as administrator?') @@ -34,7 +66,7 @@ def win_OpenSCManager(): def win_install_service(service_name, cmdline): manager = win_OpenSCManager() try: - h = advapi32.CreateServiceA( + h = advapi32.CreateServiceW( manager, service_name, None, SC_MANAGER_CREATE_SERVICE, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, @@ -50,7 +82,7 @@ def win_install_service(service_name, cmdline): def win_uninstall_service(service_name): manager = win_OpenSCManager() try: - h = advapi32.OpenServiceA(manager, service_name, DELETE) + h = advapi32.OpenServiceW(manager, service_name, DELETE) if not h: raise OSError('Could not find service %s: %s' % ( service_name, ctypes.FormatError())) @@ -64,17 +96,90 @@ def win_uninstall_service(service_name): advapi32.CloseServiceHandle(manager) -def install_service(bind): - fn = os.path.normpath(__file__) - cmdline = '"%s" "%s" -s -b "%s"' % (sys.executable, fn, bind) - win_install_service('youtubedl_builder', cmdline) +def win_service_report_event(service_name, msg, is_error=True): + with open('C:/sshkeys/log', 'a', encoding='utf-8') as f: + f.write(msg + '\n') + + event_log = advapi32.RegisterEventSourceW(None, service_name) + if not event_log: + raise OSError('Could not report event: %s' % ctypes.FormatError()) + + try: + type_id = 0x0001 if is_error else 0x0004 + event_id = 0xc0000000 if is_error else 0x40000000 + lines = _ctypes_array(LPTSTR, [msg]) + + if not advapi32.ReportEventW( + event_log, type_id, 0, event_id, None, len(lines), 0, + lines, None): + raise OSError('Event reporting failed: %s' % ctypes.FormatError()) + finally: + advapi32.DeregisterEventSource(event_log) + + +def win_service_handler(stop_event, *args): + try: + raise ValueError('Handler called with args ' + repr(args)) + TODO + except Exception as e: + tb = traceback.format_exc() + msg = str(e) + '\n' + tb + win_service_report_event(service_name, msg, is_error=True) + raise + + +def win_service_set_status(handle, status_code): + svcStatus = SERVICE_STATUS() + svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS + svcStatus.dwCurrentState = status_code + svcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP + + svcStatus.dwServiceSpecificExitCode = 0 + if not advapi32.SetServiceStatus(handle, ctypes.byref(svcStatus)): + raise OSError('SetServiceStatus failed: %r' % ctypes.FormatError()) -def uninstall_service(): - win_uninstall_service('youtubedl_builder') +def win_service_main(service_name, real_main, argc, argv_raw): + try: + #args = [argv_raw[i].value for i in range(argc)] + stop_event = threading.Event() + handler = HandlerEx(functools.partial(stop_event, win_service_handler)) + h = advapi32.RegisterServiceCtrlHandlerExW(service_name, handler, None) + if not h: + raise OSError('Handler registration failed: %s' % + ctypes.FormatError()) + + TODO + except Exception as e: + tb = traceback.format_exc() + msg = str(e) + '\n' + tb + win_service_report_event(service_name, msg, is_error=True) + raise -def main(argv): + +def win_service_start(service_name, real_main): + try: + cb = START_CALLBACK( + functools.partial(win_service_main, service_name, real_main)) + dispatch_table = _ctypes_array(SERVICE_TABLE_ENTRY, [ + SERVICE_TABLE_ENTRY( + service_name, + cb + ), + SERVICE_TABLE_ENTRY(None, ctypes.cast(None, START_CALLBACK)) + ]) + + if not advapi32.StartServiceCtrlDispatcherW(dispatch_table): + raise OSError('ctypes start failed: %s' % ctypes.FormatError()) + except Exception as e: + tb = traceback.format_exc() + msg = str(e) + '\n' + tb + win_service_report_event(service_name, msg, is_error=True) + raise + + +def main(args=None): parser = argparse.ArgumentParser() parser.add_argument('-i', '--install', action='store_const', dest='action', const='install', @@ -83,18 +188,26 @@ def main(argv): action='store_const', dest='action', const='uninstall', help='Remove Windows service') parser.add_argument('-s', '--service', - action='store_const', dest='action', const='servce', + action='store_const', dest='action', const='service', help='Run as a Windows service') parser.add_argument('-b', '--bind', metavar='', action='store', default='localhost:8142', help='Bind to host:port (default %default)') - options = parser.parse_args() + options = parser.parse_args(args=args) if options.action == 'install': - return install_service(options.bind) + fn = os.path.abspath(__file__).replace('v:', '\\\\vboxsrv\\vbox') + cmdline = '%s %s -s -b %s' % (sys.executable, fn, options.bind) + win_install_service(SVCNAME, cmdline) + return if options.action == 'uninstall': - return uninstall_service() + win_uninstall_service(SVCNAME) + return + + if options.action == 'service': + win_service_start(SVCNAME, main) + return host, port_str = options.bind.split(':') port = int(port_str) @@ -289,4 +402,4 @@ class BuildHTTPRequestHandler(BaseHTTPRequestHandler): #============================================================================== if __name__ == '__main__': - main(sys.argv[1:]) + main() -- cgit v1.2.3