<s> import re <EOL> import os <EOL> import sys <EOL> import glob <EOL> import stat <EOL> import time <EOL> import errno <EOL> import subprocess <EOL> import getpass <EOL> import pwd <EOL> import tempfile <EOL> from . import manager <EOL> from . shared import find_config , open_resource <EOL> from . import user_client <EOL> import json <EOL> import socket <EOL> from . import servers <EOL> from twisted . internet import reactor <EOL> usage_text = "<STR_LIT>" <EOL> help_text = """<STR_LIT>""" <EOL> help_sub_text = """<STR_LIT>""" <EOL> class Mark2Error ( Exception ) : <EOL> def __init__ ( self , error ) : <EOL> self . error = error <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % self . error <EOL> class Mark2ParseError ( Mark2Error ) : <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( usage_text , self . error ) <EOL> class Command ( object ) : <EOL> name = "<STR_LIT>" <EOL> value_spec = "<STR_LIT>" <EOL> options_spec = tuple ( ) <EOL> def __init__ ( self ) : <EOL> pass <EOL> def do_start ( self ) : <EOL> pass <EOL> def do_end ( self ) : <EOL> pass <EOL> @ classmethod <EOL> def get_bases ( cls ) : <EOL> o = [ ] <EOL> while True : <EOL> cls = cls . __bases__ [ <NUM_LIT:0> ] <EOL> if cls is object : <EOL> break <EOL> o . append ( cls ) <EOL> return o <EOL> @ classmethod <EOL> def get_options_spec ( cls ) : <EOL> return sum ( [ list ( b . options_spec ) for b in [ cls ] + cls . get_bases ( ) [ : : - <NUM_LIT:1> ] ] , [ ] ) <EOL> def parse_options ( self , c_args ) : <EOL> options = { } <EOL> options_tys = { } <EOL> for opt in self . __class__ . get_options_spec ( ) : <EOL> for flag in opt [ <NUM_LIT:1> ] : <EOL> options_tys [ flag ] = opt <EOL> while len ( c_args ) > <NUM_LIT:0> : <EOL> head = c_args [ <NUM_LIT:0> ] <EOL> if head [ <NUM_LIT:0> ] != '<STR_LIT:->' : <EOL> break <EOL> elif head == '<STR_LIT>' : <EOL> c_args . pop ( <NUM_LIT:0> ) <EOL> break <EOL> elif head in options_tys : <EOL> opt = options_tys [ c_args . pop ( <NUM_LIT:0> ) ] <EOL> try : <EOL> options [ opt [ <NUM_LIT:0> ] ] = c_args . pop ( <NUM_LIT:0> ) if opt [ <NUM_LIT:2> ] != '<STR_LIT>' else True <EOL> except IndexError : <EOL> raise Mark2ParseError ( "<STR_LIT>" % opt [ <NUM_LIT:0> ] ) <EOL> else : <EOL> raise Mark2Error ( "<STR_LIT>" % ( self . name , head ) ) <EOL> self . options = options <EOL> self . value = '<STR_LIT:U+0020>' . join ( c_args ) if len ( c_args ) else None <EOL> def start ( self ) : <EOL> bases = self . __class__ . get_bases ( ) <EOL> for b in bases [ : : - <NUM_LIT:1> ] : <EOL> b . do_start ( self ) <EOL> self . run ( ) <EOL> for b in bases : <EOL> b . do_end ( self ) <EOL> def run ( self ) : <EOL> raise NotImplementedError <EOL> class CommandTyStateful ( Command ) : <EOL> options_spec = ( ( '<STR_LIT>' , ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' , '<STR_LIT>' ) , ) <EOL> def do_start ( self ) : <EOL> self . shared_path = self . options . get ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . make_writable ( self . shared_path ) <EOL> o = [ ] <EOL> for path in glob . glob ( self . shared ( '<STR_LIT>' , '<STR_LIT:*>' ) ) : <EOL> with open ( path ) as fp : <EOL> pid = int ( fp . read ( ) ) <EOL> try : <EOL> os . kill ( pid , <NUM_LIT:0> ) <EOL> except OSError as err : <EOL> if err . errno == errno . ESRCH : <EOL> os . remove ( path ) <EOL> continue <EOL> f = os . path . basename ( path ) <EOL> f = os . path . splitext ( f ) [ <NUM_LIT:0> ] <EOL> o . append ( f ) <EOL> self . servers = sorted ( o ) <EOL> def shared ( self , ty , name = None ) : <EOL> if name is None : <EOL> name = self . server_name <EOL> return os . path . join ( self . shared_path , "<STR_LIT>" % ( name , ty ) ) <EOL> def make_writable ( self , directory ) : <EOL> need_modes = stat . S_IRWXU | stat . S_IRGRP | stat . S_IXGRP | stat . S_IROTH | stat . S_IXOTH | stat . S_IRWXG | stat . S_IRWXO <EOL> good_modes = stat . S_IRWXU | stat . S_IRWXG | stat . S_IRWXO | stat . S_ISVTX <EOL> if not os . path . exists ( directory ) : <EOL> os . makedirs ( directory , good_modes ) <EOL> st = os . stat ( directory ) <EOL> if ( st . st_mode & need_modes ) == need_modes : <EOL> return True <EOL> try : <EOL> os . chmod ( directory , good_modes ) <EOL> return True <EOL> except Exception : <EOL> raise Mark2Error ( '<STR_LIT>' % directory ) <EOL> class CommandTySelective ( CommandTyStateful ) : <EOL> options_spec = ( ( '<STR_LIT:name>' , ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' , '<STR_LIT>' ) , ) <EOL> name_should_exist = True <EOL> server_name = None <EOL> def do_start ( self ) : <EOL> name = self . options . get ( '<STR_LIT:name>' , None ) <EOL> if self . name_should_exist : <EOL> if name is None : <EOL> if len ( self . servers ) > <NUM_LIT:0> : <EOL> name = self . servers [ <NUM_LIT:0> ] <EOL> else : <EOL> raise Mark2Error ( "<STR_LIT>" ) <EOL> elif name not in self . servers : <EOL> raise Mark2Error ( "<STR_LIT>" % name ) <EOL> else : <EOL> if name is None : <EOL> pass <EOL> elif name in self . servers : <EOL> raise Mark2Error ( "<STR_LIT>" % name ) <EOL> self . server_name = name <EOL> def do_send ( self , data ) : <EOL> d = { <EOL> '<STR_LIT:type>' : '<STR_LIT:input>' , <EOL> '<STR_LIT:user>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : data <EOL> } <EOL> d = json . dumps ( d ) + "<STR_LIT:\n>" <EOL> s = socket . socket ( socket . AF_UNIX , socket . SOCK_STREAM ) <EOL> s . connect ( self . shared ( '<STR_LIT>' ) ) <EOL> s . send ( d ) <EOL> s . close ( ) <EOL> class CommandTyTerminal ( CommandTySelective ) : <EOL> options_spec = ( <EOL> ( '<STR_LIT>' , ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' , '<STR_LIT>' ) , <EOL> ( '<STR_LIT>' , ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' , '<STR_LIT>' ) , <EOL> ( '<STR_LIT>' , ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> wait = None <EOL> wait_from_start = False <EOL> only = False <EOL> def do_end ( self ) : <EOL> if '<STR_LIT>' in self . options : <EOL> self . wait = self . options [ '<STR_LIT>' ] <EOL> if '<STR_LIT>' in self . options : <EOL> self . only = True <EOL> if '<STR_LIT>' in self . options : <EOL> self . wait = None <EOL> try : <EOL> self . do_wait ( ) <EOL> except KeyboardInterrupt : <EOL> pass <EOL> def do_wait ( self ) : <EOL> if self . wait is None : <EOL> return <EOL> while not os . path . exists ( self . shared ( '<STR_LIT>' ) ) : <EOL> time . sleep ( <NUM_LIT:0.1> ) <EOL> with open ( self . shared ( '<STR_LIT>' ) , '<STR_LIT:r>' ) as f : <EOL> if not self . wait_from_start : <EOL> f . seek ( <NUM_LIT:0> , <NUM_LIT:2> ) <EOL> while True : <EOL> line = f . readline ( ) . rstrip ( ) <EOL> if not line : <EOL> time . sleep ( <NUM_LIT:0.1> ) <EOL> continue <EOL> if line [ <NUM_LIT:0> ] in ( "<STR_LIT:U+0020>" , "<STR_LIT:\t>" ) : <EOL> print line <EOL> continue <EOL> line = line . split ( "<STR_LIT:U+0020>" , <NUM_LIT:3> ) <EOL> if line [ <NUM_LIT:2> ] == '<STR_LIT>' : <EOL> line2 = line [ <NUM_LIT:3> ] . split ( "<STR_LIT:U+0020>" , <NUM_LIT:2> ) <EOL> if re . search ( self . wait , line2 [ <NUM_LIT:2> ] ) : <EOL> print line [ <NUM_LIT:3> ] <EOL> return <EOL> elif not self . only : <EOL> print line [ <NUM_LIT:3> ] <EOL> class CommandHelp ( Command ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> value_spec = "<STR_LIT>" <EOL> def run ( self ) : <EOL> if self . value is None : <EOL> print help_text . format ( <EOL> usage = usage_text , <EOL> commands = self . columns ( [ ( c . name , c . value_spec , c . __doc__ ) for c in commands ] ) ) <EOL> elif self . value in commands_d : <EOL> cls = commands_d [ self . value ] <EOL> print help_sub_text . format ( <EOL> subcommand = self . value , <EOL> doc = cls . __doc__ , <EOL> value_spec = cls . value_spec <EOL> ) <EOL> opts = cls . get_options_spec ( ) <EOL> if len ( opts ) > <NUM_LIT:0> : <EOL> print "<STR_LIT>" <EOL> print self . columns ( [ ( '<STR_LIT:U+0020>' . join ( o [ <NUM_LIT:1> ] ) , o [ <NUM_LIT:2> ] , o [ <NUM_LIT:3> ] ) for o in opts ] ) + "<STR_LIT:\n>" <EOL> else : <EOL> raise Mark2Error ( "<STR_LIT>" % self . value ) <EOL> def columns ( self , data ) : <EOL> o = [ ] <EOL> for tokens in data : <EOL> line = "<STR_LIT>" <EOL> for i , token in enumerate ( tokens ) : <EOL> line += token <EOL> line += "<STR_LIT:U+0020>" * ( ( ( i + <NUM_LIT:1> ) * <NUM_LIT:12> ) - len ( line ) ) <EOL> o . append ( line ) <EOL> return "<STR_LIT:\n>" . join ( ( "<STR_LIT:U+0020>" + l for l in o ) ) <EOL> class CommandStart ( CommandTyTerminal ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT:start>' <EOL> value_spec = '<STR_LIT>' <EOL> name_should_exist = False <EOL> def get_server_path ( self ) : <EOL> self . jar_file = None <EOL> self . server_path = os . path . realpath ( "<STR_LIT>" if self . value is None else self . value ) <EOL> if os . path . isdir ( self . server_path ) : <EOL> pass <EOL> elif os . path . isfile ( self . server_path ) : <EOL> if self . server_path . endswith ( '<STR_LIT>' ) : <EOL> self . server_path , self . jar_file = os . path . split ( self . server_path ) <EOL> else : <EOL> raise Mark2Error ( "<STR_LIT>" + self . server_path ) <EOL> else : <EOL> raise Mark2Error ( "<STR_LIT>" + self . server_path ) <EOL> def check_config ( self ) : <EOL> new_cfg = find_config ( '<STR_LIT>' , ignore_errors = True ) <EOL> if os . path . exists ( new_cfg ) : <EOL> return <EOL> if os . path . exists ( os . path . realpath ( os . path . join ( os . path . dirname ( __file__ ) , '<STR_LIT:..>' , '<STR_LIT>' ) ) ) : <EOL> new_dir = os . path . dirname ( new_cfg ) <EOL> raise Mark2Error ( "<STR_LIT>" . format ( new_dir ) ) <EOL> else : <EOL> raise Mark2Error ( "<STR_LIT>" ) <EOL> def check_ownership ( self ) : <EOL> d_user = pwd . getpwuid ( os . stat ( self . server_path ) . st_uid ) . pw_name <EOL> m_user = getpass . getuser ( ) <EOL> if d_user != m_user : <EOL> e = "<STR_LIT>" + "<STR_LIT>" <EOL> raise Mark2Error ( e . format ( d_user = d_user , m_user = m_user ) ) <EOL> def daemonize ( self ) : <EOL> if os . fork ( ) > <NUM_LIT:0> : <EOL> return <NUM_LIT:1> <EOL> os . chdir ( "<STR_LIT:.>" ) <EOL> os . setsid ( ) <EOL> os . umask ( <NUM_LIT:0> ) <EOL> if os . fork ( ) > <NUM_LIT:0> : <EOL> sys . exit ( <NUM_LIT:0> ) <EOL> null = os . open ( '<STR_LIT>' , os . O_RDWR ) <EOL> for fileno in ( <NUM_LIT:1> , <NUM_LIT:2> , <NUM_LIT:3> ) : <EOL> try : <EOL> os . dup2 ( null , fileno ) <EOL> except : <EOL> pass <EOL> return <NUM_LIT:0> <EOL> def run ( self ) : <EOL> self . get_server_path ( ) <EOL> if self . server_name is None : <EOL> self . server_name = os . path . basename ( self . server_path ) <EOL> if self . server_name in self . servers : <EOL> raise Mark2Error ( "<STR_LIT>" % self . server_name ) <EOL> self . check_config ( ) <EOL> self . check_ownership ( ) <EOL> for x in ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) : <EOL> if os . path . exists ( self . shared ( x ) ) : <EOL> os . remove ( self . shared ( x ) ) <EOL> i = <NUM_LIT:1> <EOL> while True : <EOL> p = self . shared ( "<STR_LIT>" % i ) <EOL> if not os . path . exists ( p ) : <EOL> break <EOL> os . remove ( p ) <EOL> i += <NUM_LIT:1> <EOL> if self . daemonize ( ) == <NUM_LIT:0> : <EOL> with open ( self . shared ( '<STR_LIT>' ) , '<STR_LIT:w>' ) as f : <EOL> f . write ( "<STR_LIT>" . format ( os . getpid ( ) ) ) <EOL> mgr = manager . Manager ( self . shared_path , self . server_name , self . server_path , self . jar_file ) <EOL> reactor . callWhenRunning ( mgr . startup ) <EOL> reactor . run ( ) <EOL> sys . exit ( <NUM_LIT:0> ) <EOL> self . wait = '<STR_LIT>' <EOL> self . wait_from_start = True <EOL> class CommandConfig ( Command ) : <EOL> """<STR_LIT>""" <EOL> options_spec = ( ( '<STR_LIT>' , ( '<STR_LIT>' , '<STR_LIT>' ) , '<STR_LIT>' , '<STR_LIT>' ) , ) <EOL> name = '<STR_LIT>' <EOL> def check_executable ( self , cmd ) : <EOL> return subprocess . call ( <EOL> [ "<STR_LIT>" , "<STR_LIT>" , cmd ] , <EOL> stdout = subprocess . PIPE , <EOL> stderr = subprocess . PIPE <EOL> ) == <NUM_LIT:0> <EOL> def copy_config ( self , src , dest , header = '<STR_LIT>' ) : <EOL> f0 = src <EOL> f1 = dest <EOL> l0 = '<STR_LIT>' <EOL> while l0 . strip ( ) == '<STR_LIT>' or l0 . startswith ( '<STR_LIT>' ) : <EOL> l0 = f0 . readline ( ) <EOL> f1 . write ( header ) <EOL> while l0 != '<STR_LIT>' : <EOL> f1 . write ( l0 ) <EOL> l0 = f0 . readline ( ) <EOL> f0 . close ( ) <EOL> f1 . close ( ) <EOL> def diff_config ( self , src , dest ) : <EOL> diff = "<STR_LIT>" <EOL> d0 = src . readlines ( ) <EOL> d1 = dest . readlines ( ) <EOL> import difflib <EOL> ignore = "<STR_LIT>" <EOL> s = difflib . SequenceMatcher ( lambda x : x in ignore , d0 , d1 ) <EOL> for tag , i0 , i1 , j0 , j1 in s . get_opcodes ( ) : <EOL> if tag in ( '<STR_LIT:replace>' , '<STR_LIT>' ) : <EOL> for l1 in d1 [ j0 : j1 ] : <EOL> if l1 . strip ( ignore ) != '<STR_LIT>' : <EOL> diff += l1 <EOL> return diff <EOL> def run ( self ) : <EOL> path_old = '<STR_LIT>' <EOL> path_new = find_config ( '<STR_LIT>' ) <EOL> def write_config ( data = '<STR_LIT>' ) : <EOL> data = "<STR_LIT>" + data <EOL> with open ( path_new , '<STR_LIT:w>' ) as file_new : <EOL> file_new . write ( data ) <EOL> if "<STR_LIT>" not in os . environ and self . options . get ( '<STR_LIT>' , False ) : <EOL> response = raw_input ( '<STR_LIT>' ) or '<STR_LIT:yes>' <EOL> if response != '<STR_LIT:yes>' : <EOL> return write_config ( ) if not os . path . exists ( path_new ) else None <EOL> editors = [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> if "<STR_LIT>" in os . environ : <EOL> editors . insert ( <NUM_LIT:0> , os . environ [ "<STR_LIT>" ] ) <EOL> for editor in editors : <EOL> if self . check_executable ( editor ) : <EOL> break <EOL> else : <EOL> if not os . path . exists ( path_new ) : <EOL> write_config ( ) <EOL> raise Mark2Error ( "<STR_LIT>" ) <EOL> if os . path . exists ( path_new ) : <EOL> subprocess . call ( [ editor , path_new ] ) <EOL> else : <EOL> fd_tmp , path_tmp = tempfile . mkstemp ( prefix = '<STR_LIT>' , text = True ) <EOL> with open_resource ( path_old ) as src : <EOL> with open ( path_tmp , '<STR_LIT:w>' ) as dst : <EOL> self . copy_config ( src , dst ) <EOL> subprocess . call ( [ editor , path_tmp ] ) <EOL> with open_resource ( path_old ) as src : <EOL> with open ( path_tmp , '<STR_LIT:r>' ) as dst : <EOL> write_config ( self . diff_config ( src , dst ) ) <EOL> os . remove ( path_tmp ) <EOL> class CommandList ( CommandTyStateful ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT:list>' <EOL> def run ( self ) : <EOL> for s in self . servers : <EOL> print s <EOL> class CommandAttach ( CommandTySelective ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> def run ( self ) : <EOL> f = user_client . UserClientFactory ( self . server_name , self . shared_path ) <EOL> f . main ( ) <EOL> class CommandStop ( CommandTyTerminal ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> def run ( self ) : <EOL> self . do_send ( '<STR_LIT>' ) <EOL> self . wait = '<STR_LIT>' <EOL> class CommandKill ( CommandTyTerminal ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> def run ( self ) : <EOL> self . do_send ( '<STR_LIT>' ) <EOL> self . wait = '<STR_LIT>' <EOL> class CommandSend ( CommandTyTerminal ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> value_spec = '<STR_LIT>' <EOL> def run ( self ) : <EOL> if self . value is None : <EOL> raise Mark2ParseError ( "<STR_LIT>" ) <EOL> self . do_send ( self . value ) <EOL> class CommandJarList ( Command ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> def run ( self ) : <EOL> def err ( what ) : <EOL> if reactor . running : reactor . stop ( ) <EOL> print "<STR_LIT>" % what . value <EOL> def handle ( listing ) : <EOL> if reactor . running : reactor . stop ( ) <EOL> if len ( listing ) == <NUM_LIT:0> : <EOL> print "<STR_LIT>" <EOL> else : <EOL> print "<STR_LIT>" <EOL> print listing <EOL> def start ( ) : <EOL> d = servers . jar_list ( ) <EOL> d . addCallbacks ( handle , err ) <EOL> reactor . callWhenRunning ( start ) <EOL> reactor . run ( ) <EOL> class CommandJarGet ( Command ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' <EOL> value_spec = '<STR_LIT>' <EOL> def run ( self ) : <EOL> if self . value is None : <EOL> raise Mark2ParseError ( "<STR_LIT>" ) <EOL> def err ( what ) : <EOL> print "<STR_LIT>" % what . value <EOL> def handle ( ( filename , data ) ) : <EOL> reactor . stop ( ) <EOL> if os . path . exists ( filename ) : <EOL> print "<STR_LIT>" % filename <EOL> else : <EOL> f = open ( filename , '<STR_LIT:wb>' ) <EOL> f . write ( data ) <EOL> f . close ( ) <EOL> print "<STR_LIT>" % filename <EOL> def start ( ) : <EOL> d = servers . jar_get ( self . value ) <EOL> d . addCallbacks ( handle , err ) <EOL> reactor . callWhenRunning ( start ) <EOL> reactor . run ( ) <EOL> commands = ( CommandHelp , CommandStart , CommandList , CommandAttach , CommandStop , CommandKill , CommandSend , CommandJarList , CommandJarGet , CommandConfig ) <EOL> commands_d = dict ( [ ( c . name , c ) for c in commands ] ) <EOL> def main ( ) : <EOL> try : <EOL> c_args = sys . argv [ <NUM_LIT:1> : ] <EOL> if len ( c_args ) == <NUM_LIT:0> : <EOL> command_name = '<STR_LIT>' <EOL> else : <EOL> command_name = c_args . pop ( <NUM_LIT:0> ) <EOL> command_cls = commands_d . get ( command_name , None ) <EOL> if command_cls is None : <EOL> raise Mark2ParseError ( "<STR_LIT>" % command_name ) <EOL> command = command_cls ( ) <EOL> command . parse_options ( c_args ) <EOL> command . start ( ) <EOL> return <NUM_LIT:0> <EOL> except Mark2Error as e : <EOL> print e <EOL> return <NUM_LIT:1> </s>
