1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6236dae4SAndroid Build Coastguard Worker# -*- coding: utf-8 -*- 3*6236dae4SAndroid Build Coastguard Worker# 4*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 5*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 6*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 7*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 8*6236dae4SAndroid Build Coastguard Worker# 9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 10*6236dae4SAndroid Build Coastguard Worker# 11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 14*6236dae4SAndroid Build Coastguard Worker# 15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 18*6236dae4SAndroid Build Coastguard Worker# 19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 21*6236dae4SAndroid Build Coastguard Worker# 22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 23*6236dae4SAndroid Build Coastguard Worker# 24*6236dae4SAndroid Build Coastguard Worker"""A telnet server which negotiates.""" 25*6236dae4SAndroid Build Coastguard Worker 26*6236dae4SAndroid Build Coastguard Workerfrom __future__ import (absolute_import, division, print_function, 27*6236dae4SAndroid Build Coastguard Worker unicode_literals) 28*6236dae4SAndroid Build Coastguard Worker 29*6236dae4SAndroid Build Coastguard Workerimport argparse 30*6236dae4SAndroid Build Coastguard Workerimport logging 31*6236dae4SAndroid Build Coastguard Workerimport os 32*6236dae4SAndroid Build Coastguard Workerimport socket 33*6236dae4SAndroid Build Coastguard Workerimport sys 34*6236dae4SAndroid Build Coastguard Worker 35*6236dae4SAndroid Build Coastguard Workerfrom util import ClosingFileHandler 36*6236dae4SAndroid Build Coastguard Worker 37*6236dae4SAndroid Build Coastguard Workerif sys.version_info.major >= 3: 38*6236dae4SAndroid Build Coastguard Worker import socketserver 39*6236dae4SAndroid Build Coastguard Workerelse: 40*6236dae4SAndroid Build Coastguard Worker import SocketServer as socketserver 41*6236dae4SAndroid Build Coastguard Worker 42*6236dae4SAndroid Build Coastguard Workerlog = logging.getLogger(__name__) 43*6236dae4SAndroid Build Coastguard WorkerHOST = "localhost" 44*6236dae4SAndroid Build Coastguard WorkerIDENT = "NTEL" 45*6236dae4SAndroid Build Coastguard Worker 46*6236dae4SAndroid Build Coastguard Worker 47*6236dae4SAndroid Build Coastguard Worker# The strings that indicate the test framework is checking our aliveness 48*6236dae4SAndroid Build Coastguard WorkerVERIFIED_REQ = "verifiedserver" 49*6236dae4SAndroid Build Coastguard WorkerVERIFIED_RSP = "WE ROOLZ: {pid}" 50*6236dae4SAndroid Build Coastguard Worker 51*6236dae4SAndroid Build Coastguard Worker 52*6236dae4SAndroid Build Coastguard Workerdef telnetserver(options): 53*6236dae4SAndroid Build Coastguard Worker """Start up a TCP server with a telnet handler and serve DICT requests forever.""" 54*6236dae4SAndroid Build Coastguard Worker if options.pidfile: 55*6236dae4SAndroid Build Coastguard Worker pid = os.getpid() 56*6236dae4SAndroid Build Coastguard Worker # see tests/server/util.c function write_pidfile 57*6236dae4SAndroid Build Coastguard Worker if os.name == "nt": 58*6236dae4SAndroid Build Coastguard Worker pid += 65536 59*6236dae4SAndroid Build Coastguard Worker with open(options.pidfile, "w") as f: 60*6236dae4SAndroid Build Coastguard Worker f.write(str(pid)) 61*6236dae4SAndroid Build Coastguard Worker 62*6236dae4SAndroid Build Coastguard Worker local_bind = (HOST, options.port) 63*6236dae4SAndroid Build Coastguard Worker log.info("Listening on %s", local_bind) 64*6236dae4SAndroid Build Coastguard Worker 65*6236dae4SAndroid Build Coastguard Worker # Need to set the allow_reuse on the class, not on the instance. 66*6236dae4SAndroid Build Coastguard Worker socketserver.TCPServer.allow_reuse_address = True 67*6236dae4SAndroid Build Coastguard Worker with socketserver.TCPServer(local_bind, NegotiatingTelnetHandler) as server: 68*6236dae4SAndroid Build Coastguard Worker server.serve_forever() 69*6236dae4SAndroid Build Coastguard Worker # leaving `with` calls server.close() automatically 70*6236dae4SAndroid Build Coastguard Worker return ScriptRC.SUCCESS 71*6236dae4SAndroid Build Coastguard Worker 72*6236dae4SAndroid Build Coastguard Worker 73*6236dae4SAndroid Build Coastguard Workerclass NegotiatingTelnetHandler(socketserver.BaseRequestHandler): 74*6236dae4SAndroid Build Coastguard Worker """Handler class for Telnet connections.""" 75*6236dae4SAndroid Build Coastguard Worker 76*6236dae4SAndroid Build Coastguard Worker def handle(self): 77*6236dae4SAndroid Build Coastguard Worker """Negotiates options before reading data.""" 78*6236dae4SAndroid Build Coastguard Worker neg = Negotiator(self.request) 79*6236dae4SAndroid Build Coastguard Worker 80*6236dae4SAndroid Build Coastguard Worker try: 81*6236dae4SAndroid Build Coastguard Worker # Send some initial negotiations. 82*6236dae4SAndroid Build Coastguard Worker neg.send_do("NEW_ENVIRON") 83*6236dae4SAndroid Build Coastguard Worker neg.send_will("NEW_ENVIRON") 84*6236dae4SAndroid Build Coastguard Worker neg.send_dont("NAWS") 85*6236dae4SAndroid Build Coastguard Worker neg.send_wont("NAWS") 86*6236dae4SAndroid Build Coastguard Worker 87*6236dae4SAndroid Build Coastguard Worker # Get the data passed through the negotiator 88*6236dae4SAndroid Build Coastguard Worker data = neg.recv(4*1024) 89*6236dae4SAndroid Build Coastguard Worker log.debug("Incoming data: %r", data) 90*6236dae4SAndroid Build Coastguard Worker 91*6236dae4SAndroid Build Coastguard Worker if VERIFIED_REQ.encode('utf-8') in data: 92*6236dae4SAndroid Build Coastguard Worker log.debug("Received verification request from test framework") 93*6236dae4SAndroid Build Coastguard Worker pid = os.getpid() 94*6236dae4SAndroid Build Coastguard Worker # see tests/server/util.c function write_pidfile 95*6236dae4SAndroid Build Coastguard Worker if os.name == "nt": 96*6236dae4SAndroid Build Coastguard Worker pid += 65536 97*6236dae4SAndroid Build Coastguard Worker response = VERIFIED_RSP.format(pid=pid) 98*6236dae4SAndroid Build Coastguard Worker response_data = response.encode('utf-8') 99*6236dae4SAndroid Build Coastguard Worker else: 100*6236dae4SAndroid Build Coastguard Worker log.debug("Received normal request - echoing back") 101*6236dae4SAndroid Build Coastguard Worker response_data = data.decode('utf-8').strip().encode('utf-8') 102*6236dae4SAndroid Build Coastguard Worker 103*6236dae4SAndroid Build Coastguard Worker if response_data: 104*6236dae4SAndroid Build Coastguard Worker log.debug("Sending %r", response_data) 105*6236dae4SAndroid Build Coastguard Worker self.request.sendall(response_data) 106*6236dae4SAndroid Build Coastguard Worker 107*6236dae4SAndroid Build Coastguard Worker # put some effort into making a clean socket shutdown 108*6236dae4SAndroid Build Coastguard Worker # that does not give the client ECONNRESET 109*6236dae4SAndroid Build Coastguard Worker self.request.settimeout(0.1) 110*6236dae4SAndroid Build Coastguard Worker self.request.recv(4*1024) 111*6236dae4SAndroid Build Coastguard Worker self.request.shutdown(socket.SHUT_RDWR) 112*6236dae4SAndroid Build Coastguard Worker 113*6236dae4SAndroid Build Coastguard Worker except IOError: 114*6236dae4SAndroid Build Coastguard Worker log.exception("IOError hit during request") 115*6236dae4SAndroid Build Coastguard Worker 116*6236dae4SAndroid Build Coastguard Worker 117*6236dae4SAndroid Build Coastguard Workerclass Negotiator(object): 118*6236dae4SAndroid Build Coastguard Worker NO_NEG = 0 119*6236dae4SAndroid Build Coastguard Worker START_NEG = 1 120*6236dae4SAndroid Build Coastguard Worker WILL = 2 121*6236dae4SAndroid Build Coastguard Worker WONT = 3 122*6236dae4SAndroid Build Coastguard Worker DO = 4 123*6236dae4SAndroid Build Coastguard Worker DONT = 5 124*6236dae4SAndroid Build Coastguard Worker 125*6236dae4SAndroid Build Coastguard Worker def __init__(self, tcp): 126*6236dae4SAndroid Build Coastguard Worker self.tcp = tcp 127*6236dae4SAndroid Build Coastguard Worker self.state = self.NO_NEG 128*6236dae4SAndroid Build Coastguard Worker 129*6236dae4SAndroid Build Coastguard Worker def recv(self, bytes): 130*6236dae4SAndroid Build Coastguard Worker """ 131*6236dae4SAndroid Build Coastguard Worker Read bytes from TCP, handling negotiation sequences. 132*6236dae4SAndroid Build Coastguard Worker 133*6236dae4SAndroid Build Coastguard Worker :param bytes: Number of bytes to read 134*6236dae4SAndroid Build Coastguard Worker :return: a buffer of bytes 135*6236dae4SAndroid Build Coastguard Worker """ 136*6236dae4SAndroid Build Coastguard Worker buffer = bytearray() 137*6236dae4SAndroid Build Coastguard Worker 138*6236dae4SAndroid Build Coastguard Worker # If we keep receiving negotiation sequences, we won't fill the buffer. 139*6236dae4SAndroid Build Coastguard Worker # Keep looping while we can, and until we have something to give back 140*6236dae4SAndroid Build Coastguard Worker # to the caller. 141*6236dae4SAndroid Build Coastguard Worker while len(buffer) == 0: 142*6236dae4SAndroid Build Coastguard Worker data = self.tcp.recv(bytes) 143*6236dae4SAndroid Build Coastguard Worker if not data: 144*6236dae4SAndroid Build Coastguard Worker # TCP failed to give us any data. Break out. 145*6236dae4SAndroid Build Coastguard Worker break 146*6236dae4SAndroid Build Coastguard Worker 147*6236dae4SAndroid Build Coastguard Worker for byte_int in bytearray(data): 148*6236dae4SAndroid Build Coastguard Worker if self.state == self.NO_NEG: 149*6236dae4SAndroid Build Coastguard Worker self.no_neg(byte_int, buffer) 150*6236dae4SAndroid Build Coastguard Worker elif self.state == self.START_NEG: 151*6236dae4SAndroid Build Coastguard Worker self.start_neg(byte_int) 152*6236dae4SAndroid Build Coastguard Worker elif self.state in [self.WILL, self.WONT, self.DO, self.DONT]: 153*6236dae4SAndroid Build Coastguard Worker self.handle_option(byte_int) 154*6236dae4SAndroid Build Coastguard Worker else: 155*6236dae4SAndroid Build Coastguard Worker # Received an unexpected byte. Stop negotiations 156*6236dae4SAndroid Build Coastguard Worker log.error("Unexpected byte %s in state %s", 157*6236dae4SAndroid Build Coastguard Worker byte_int, 158*6236dae4SAndroid Build Coastguard Worker self.state) 159*6236dae4SAndroid Build Coastguard Worker self.state = self.NO_NEG 160*6236dae4SAndroid Build Coastguard Worker 161*6236dae4SAndroid Build Coastguard Worker return buffer 162*6236dae4SAndroid Build Coastguard Worker 163*6236dae4SAndroid Build Coastguard Worker def no_neg(self, byte_int, buffer): 164*6236dae4SAndroid Build Coastguard Worker # Not negotiating anything thus far. Check to see if we 165*6236dae4SAndroid Build Coastguard Worker # should. 166*6236dae4SAndroid Build Coastguard Worker if byte_int == NegTokens.IAC: 167*6236dae4SAndroid Build Coastguard Worker # Start negotiation 168*6236dae4SAndroid Build Coastguard Worker log.debug("Starting negotiation (IAC)") 169*6236dae4SAndroid Build Coastguard Worker self.state = self.START_NEG 170*6236dae4SAndroid Build Coastguard Worker else: 171*6236dae4SAndroid Build Coastguard Worker # Just append the incoming byte to the buffer 172*6236dae4SAndroid Build Coastguard Worker buffer.append(byte_int) 173*6236dae4SAndroid Build Coastguard Worker 174*6236dae4SAndroid Build Coastguard Worker def start_neg(self, byte_int): 175*6236dae4SAndroid Build Coastguard Worker # In a negotiation. 176*6236dae4SAndroid Build Coastguard Worker log.debug("In negotiation (%s)", 177*6236dae4SAndroid Build Coastguard Worker NegTokens.from_val(byte_int)) 178*6236dae4SAndroid Build Coastguard Worker 179*6236dae4SAndroid Build Coastguard Worker if byte_int == NegTokens.WILL: 180*6236dae4SAndroid Build Coastguard Worker # Client is confirming they are willing to do an option 181*6236dae4SAndroid Build Coastguard Worker log.debug("Client is willing") 182*6236dae4SAndroid Build Coastguard Worker self.state = self.WILL 183*6236dae4SAndroid Build Coastguard Worker elif byte_int == NegTokens.WONT: 184*6236dae4SAndroid Build Coastguard Worker # Client is confirming they are unwilling to do an 185*6236dae4SAndroid Build Coastguard Worker # option 186*6236dae4SAndroid Build Coastguard Worker log.debug("Client is unwilling") 187*6236dae4SAndroid Build Coastguard Worker self.state = self.WONT 188*6236dae4SAndroid Build Coastguard Worker elif byte_int == NegTokens.DO: 189*6236dae4SAndroid Build Coastguard Worker # Client is indicating they can do an option 190*6236dae4SAndroid Build Coastguard Worker log.debug("Client can do") 191*6236dae4SAndroid Build Coastguard Worker self.state = self.DO 192*6236dae4SAndroid Build Coastguard Worker elif byte_int == NegTokens.DONT: 193*6236dae4SAndroid Build Coastguard Worker # Client is indicating they can't do an option 194*6236dae4SAndroid Build Coastguard Worker log.debug("Client can't do") 195*6236dae4SAndroid Build Coastguard Worker self.state = self.DONT 196*6236dae4SAndroid Build Coastguard Worker else: 197*6236dae4SAndroid Build Coastguard Worker # Received an unexpected byte. Stop negotiations 198*6236dae4SAndroid Build Coastguard Worker log.error("Unexpected byte %s in state %s", 199*6236dae4SAndroid Build Coastguard Worker byte_int, 200*6236dae4SAndroid Build Coastguard Worker self.state) 201*6236dae4SAndroid Build Coastguard Worker self.state = self.NO_NEG 202*6236dae4SAndroid Build Coastguard Worker 203*6236dae4SAndroid Build Coastguard Worker def handle_option(self, byte_int): 204*6236dae4SAndroid Build Coastguard Worker if byte_int in [NegOptions.BINARY, 205*6236dae4SAndroid Build Coastguard Worker NegOptions.CHARSET, 206*6236dae4SAndroid Build Coastguard Worker NegOptions.SUPPRESS_GO_AHEAD, 207*6236dae4SAndroid Build Coastguard Worker NegOptions.NAWS, 208*6236dae4SAndroid Build Coastguard Worker NegOptions.NEW_ENVIRON]: 209*6236dae4SAndroid Build Coastguard Worker log.debug("Option: %s", NegOptions.from_val(byte_int)) 210*6236dae4SAndroid Build Coastguard Worker 211*6236dae4SAndroid Build Coastguard Worker # No further negotiation of this option needed. Reset the state. 212*6236dae4SAndroid Build Coastguard Worker self.state = self.NO_NEG 213*6236dae4SAndroid Build Coastguard Worker 214*6236dae4SAndroid Build Coastguard Worker else: 215*6236dae4SAndroid Build Coastguard Worker # Received an unexpected byte. Stop negotiations 216*6236dae4SAndroid Build Coastguard Worker log.error("Unexpected byte %s in state %s", 217*6236dae4SAndroid Build Coastguard Worker byte_int, 218*6236dae4SAndroid Build Coastguard Worker self.state) 219*6236dae4SAndroid Build Coastguard Worker self.state = self.NO_NEG 220*6236dae4SAndroid Build Coastguard Worker 221*6236dae4SAndroid Build Coastguard Worker def send_message(self, message_ints): 222*6236dae4SAndroid Build Coastguard Worker self.tcp.sendall(bytearray(message_ints)) 223*6236dae4SAndroid Build Coastguard Worker 224*6236dae4SAndroid Build Coastguard Worker def send_iac(self, arr): 225*6236dae4SAndroid Build Coastguard Worker message = [NegTokens.IAC] 226*6236dae4SAndroid Build Coastguard Worker message.extend(arr) 227*6236dae4SAndroid Build Coastguard Worker self.send_message(message) 228*6236dae4SAndroid Build Coastguard Worker 229*6236dae4SAndroid Build Coastguard Worker def send_do(self, option_str): 230*6236dae4SAndroid Build Coastguard Worker log.debug("Sending DO %s", option_str) 231*6236dae4SAndroid Build Coastguard Worker self.send_iac([NegTokens.DO, NegOptions.to_val(option_str)]) 232*6236dae4SAndroid Build Coastguard Worker 233*6236dae4SAndroid Build Coastguard Worker def send_dont(self, option_str): 234*6236dae4SAndroid Build Coastguard Worker log.debug("Sending DONT %s", option_str) 235*6236dae4SAndroid Build Coastguard Worker self.send_iac([NegTokens.DONT, NegOptions.to_val(option_str)]) 236*6236dae4SAndroid Build Coastguard Worker 237*6236dae4SAndroid Build Coastguard Worker def send_will(self, option_str): 238*6236dae4SAndroid Build Coastguard Worker log.debug("Sending WILL %s", option_str) 239*6236dae4SAndroid Build Coastguard Worker self.send_iac([NegTokens.WILL, NegOptions.to_val(option_str)]) 240*6236dae4SAndroid Build Coastguard Worker 241*6236dae4SAndroid Build Coastguard Worker def send_wont(self, option_str): 242*6236dae4SAndroid Build Coastguard Worker log.debug("Sending WONT %s", option_str) 243*6236dae4SAndroid Build Coastguard Worker self.send_iac([NegTokens.WONT, NegOptions.to_val(option_str)]) 244*6236dae4SAndroid Build Coastguard Worker 245*6236dae4SAndroid Build Coastguard Worker 246*6236dae4SAndroid Build Coastguard Workerclass NegBase(object): 247*6236dae4SAndroid Build Coastguard Worker @classmethod 248*6236dae4SAndroid Build Coastguard Worker def to_val(cls, name): 249*6236dae4SAndroid Build Coastguard Worker return getattr(cls, name) 250*6236dae4SAndroid Build Coastguard Worker 251*6236dae4SAndroid Build Coastguard Worker @classmethod 252*6236dae4SAndroid Build Coastguard Worker def from_val(cls, val): 253*6236dae4SAndroid Build Coastguard Worker for k in cls.__dict__: 254*6236dae4SAndroid Build Coastguard Worker if getattr(cls, k) == val: 255*6236dae4SAndroid Build Coastguard Worker return k 256*6236dae4SAndroid Build Coastguard Worker 257*6236dae4SAndroid Build Coastguard Worker return "<unknown>" 258*6236dae4SAndroid Build Coastguard Worker 259*6236dae4SAndroid Build Coastguard Worker 260*6236dae4SAndroid Build Coastguard Workerclass NegTokens(NegBase): 261*6236dae4SAndroid Build Coastguard Worker # The start of a negotiation sequence 262*6236dae4SAndroid Build Coastguard Worker IAC = 255 263*6236dae4SAndroid Build Coastguard Worker # Confirm willingness to negotiate 264*6236dae4SAndroid Build Coastguard Worker WILL = 251 265*6236dae4SAndroid Build Coastguard Worker # Confirm unwillingness to negotiate 266*6236dae4SAndroid Build Coastguard Worker WONT = 252 267*6236dae4SAndroid Build Coastguard Worker # Indicate willingness to negotiate 268*6236dae4SAndroid Build Coastguard Worker DO = 253 269*6236dae4SAndroid Build Coastguard Worker # Indicate unwillingness to negotiate 270*6236dae4SAndroid Build Coastguard Worker DONT = 254 271*6236dae4SAndroid Build Coastguard Worker 272*6236dae4SAndroid Build Coastguard Worker # The start of sub-negotiation options. 273*6236dae4SAndroid Build Coastguard Worker SB = 250 274*6236dae4SAndroid Build Coastguard Worker # The end of sub-negotiation options. 275*6236dae4SAndroid Build Coastguard Worker SE = 240 276*6236dae4SAndroid Build Coastguard Worker 277*6236dae4SAndroid Build Coastguard Worker 278*6236dae4SAndroid Build Coastguard Workerclass NegOptions(NegBase): 279*6236dae4SAndroid Build Coastguard Worker # Binary Transmission 280*6236dae4SAndroid Build Coastguard Worker BINARY = 0 281*6236dae4SAndroid Build Coastguard Worker # Suppress Go Ahead 282*6236dae4SAndroid Build Coastguard Worker SUPPRESS_GO_AHEAD = 3 283*6236dae4SAndroid Build Coastguard Worker # NAWS - width and height of client 284*6236dae4SAndroid Build Coastguard Worker NAWS = 31 285*6236dae4SAndroid Build Coastguard Worker # NEW-ENVIRON - environment variables on client 286*6236dae4SAndroid Build Coastguard Worker NEW_ENVIRON = 39 287*6236dae4SAndroid Build Coastguard Worker # Charset option 288*6236dae4SAndroid Build Coastguard Worker CHARSET = 42 289*6236dae4SAndroid Build Coastguard Worker 290*6236dae4SAndroid Build Coastguard Worker 291*6236dae4SAndroid Build Coastguard Workerdef get_options(): 292*6236dae4SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 293*6236dae4SAndroid Build Coastguard Worker 294*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--port", action="store", default=9019, 295*6236dae4SAndroid Build Coastguard Worker type=int, help="port to listen on") 296*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--verbose", action="store", type=int, default=0, 297*6236dae4SAndroid Build Coastguard Worker help="verbose output") 298*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--pidfile", action="store", 299*6236dae4SAndroid Build Coastguard Worker help="file name for the PID") 300*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--logfile", action="store", 301*6236dae4SAndroid Build Coastguard Worker help="file name for the log") 302*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--srcdir", action="store", help="test directory") 303*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--id", action="store", help="server ID") 304*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--ipv4", action="store_true", default=0, 305*6236dae4SAndroid Build Coastguard Worker help="IPv4 flag") 306*6236dae4SAndroid Build Coastguard Worker 307*6236dae4SAndroid Build Coastguard Worker return parser.parse_args() 308*6236dae4SAndroid Build Coastguard Worker 309*6236dae4SAndroid Build Coastguard Worker 310*6236dae4SAndroid Build Coastguard Workerdef setup_logging(options): 311*6236dae4SAndroid Build Coastguard Worker """Set up logging from the command line options.""" 312*6236dae4SAndroid Build Coastguard Worker root_logger = logging.getLogger() 313*6236dae4SAndroid Build Coastguard Worker add_stdout = False 314*6236dae4SAndroid Build Coastguard Worker 315*6236dae4SAndroid Build Coastguard Worker formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s " 316*6236dae4SAndroid Build Coastguard Worker "[{ident}] %(message)s" 317*6236dae4SAndroid Build Coastguard Worker .format(ident=IDENT)) 318*6236dae4SAndroid Build Coastguard Worker 319*6236dae4SAndroid Build Coastguard Worker # Write out to a logfile 320*6236dae4SAndroid Build Coastguard Worker if options.logfile: 321*6236dae4SAndroid Build Coastguard Worker handler = ClosingFileHandler(options.logfile) 322*6236dae4SAndroid Build Coastguard Worker handler.setFormatter(formatter) 323*6236dae4SAndroid Build Coastguard Worker handler.setLevel(logging.DEBUG) 324*6236dae4SAndroid Build Coastguard Worker root_logger.addHandler(handler) 325*6236dae4SAndroid Build Coastguard Worker else: 326*6236dae4SAndroid Build Coastguard Worker # The logfile wasn't specified. Add a stdout logger. 327*6236dae4SAndroid Build Coastguard Worker add_stdout = True 328*6236dae4SAndroid Build Coastguard Worker 329*6236dae4SAndroid Build Coastguard Worker if options.verbose: 330*6236dae4SAndroid Build Coastguard Worker # Add a stdout logger as well in verbose mode 331*6236dae4SAndroid Build Coastguard Worker root_logger.setLevel(logging.DEBUG) 332*6236dae4SAndroid Build Coastguard Worker add_stdout = True 333*6236dae4SAndroid Build Coastguard Worker else: 334*6236dae4SAndroid Build Coastguard Worker root_logger.setLevel(logging.INFO) 335*6236dae4SAndroid Build Coastguard Worker 336*6236dae4SAndroid Build Coastguard Worker if add_stdout: 337*6236dae4SAndroid Build Coastguard Worker stdout_handler = logging.StreamHandler(sys.stdout) 338*6236dae4SAndroid Build Coastguard Worker stdout_handler.setFormatter(formatter) 339*6236dae4SAndroid Build Coastguard Worker stdout_handler.setLevel(logging.DEBUG) 340*6236dae4SAndroid Build Coastguard Worker root_logger.addHandler(stdout_handler) 341*6236dae4SAndroid Build Coastguard Worker 342*6236dae4SAndroid Build Coastguard Worker 343*6236dae4SAndroid Build Coastguard Workerclass ScriptRC(object): 344*6236dae4SAndroid Build Coastguard Worker """Enum for script return codes.""" 345*6236dae4SAndroid Build Coastguard Worker 346*6236dae4SAndroid Build Coastguard Worker SUCCESS = 0 347*6236dae4SAndroid Build Coastguard Worker FAILURE = 1 348*6236dae4SAndroid Build Coastguard Worker EXCEPTION = 2 349*6236dae4SAndroid Build Coastguard Worker 350*6236dae4SAndroid Build Coastguard Worker 351*6236dae4SAndroid Build Coastguard Workerif __name__ == '__main__': 352*6236dae4SAndroid Build Coastguard Worker # Get the options from the user. 353*6236dae4SAndroid Build Coastguard Worker options = get_options() 354*6236dae4SAndroid Build Coastguard Worker 355*6236dae4SAndroid Build Coastguard Worker # Setup logging using the user options 356*6236dae4SAndroid Build Coastguard Worker setup_logging(options) 357*6236dae4SAndroid Build Coastguard Worker 358*6236dae4SAndroid Build Coastguard Worker # Run main script. 359*6236dae4SAndroid Build Coastguard Worker try: 360*6236dae4SAndroid Build Coastguard Worker rc = telnetserver(options) 361*6236dae4SAndroid Build Coastguard Worker except Exception: 362*6236dae4SAndroid Build Coastguard Worker log.exception('Error in telnet server') 363*6236dae4SAndroid Build Coastguard Worker rc = ScriptRC.EXCEPTION 364*6236dae4SAndroid Build Coastguard Worker 365*6236dae4SAndroid Build Coastguard Worker if options.pidfile and os.path.isfile(options.pidfile): 366*6236dae4SAndroid Build Coastguard Worker os.unlink(options.pidfile) 367*6236dae4SAndroid Build Coastguard Worker 368*6236dae4SAndroid Build Coastguard Worker log.info("Returning %d", rc) 369*6236dae4SAndroid Build Coastguard Worker sys.exit(rc) 370