#!/usr/bin/env arista-python
# Copyright (c) 2008, 2009, 2011 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.

import argparse
import os
import sys

import Ark
import FastServ
import FastServUtil

args = None

def doArgv( argv ):
   if argv:
      if argv[0] == '-c':
         exec( ' '.join( argv[ 1: ] ) )
      else:
         sys.argv = argv
         # pylint: disable-next=consider-using-with
         exec( open( argv[ 0 ] ).read(), globals() )
   else:
      import code # pylint: disable=import-outside-toplevel
      code.interact()

serviceName = None
pythonMode = None
def main():
   global args
   ap = argparse.ArgumentParser( usage="%(prog)s [OPTIONS] [<name>]" )
   ap.add_argument( "-c", "--command",
                    help="exec python code before serving",
                    metavar="CODE")
   ap.add_argument( "-d", "--daemonize", action="store_true",
                     help="daemonize and return immediately" )
   ap.add_argument( "-n", action="store_true", help="starts a namespace" )
   ap.add_argument( "-p", "--python", action="store_true", help="python mode" )
   ap.add_argument( "-f", help="specify namespace flags [nmshiu]: "
                    "n=NET, m=NS(mount), h=UTS, i=IPC, u=USER, p=PID "
                    "(-n is required, default=nm)",
                    metavar="FLAGS")
   ap.add_argument( "--logfile",
                    help="write output to LOGFILE (default=%(default)s)" )
   ap.add_argument( "--pidfile",
                    help="write process ID of server to PIDFILE "
                       "(default=%(default)s)" )
   ap.add_argument( "serviceName", metavar='name',
                    help="service name" )
   args = ap.parse_args()

   if args.f and not args.n:
      ap.error( "options flags (-f) can only be used when creating a namespace "
                "(-n)" )

   if args.logfile:
      os.close( 1 )
      os.close( 2 )
      os.open( args.logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND )
      os.dup( 1 )

   namespaceFlags = None
   if args.n:
      if args.f:
         namespaceFlags = args.f
      else:
         namespaceFlags = 'nm'

   if args.command:
      exec( args.command )

   global pythonMode
   pythonMode = args.python

   if args.daemonize:
      if os.fork() != 0:
         sys.exit()
      os.setsid()
      if os.fork() != 0:
         os._exit( 0 ) # pylint: disable=protected-access
      os.umask( 0 )
      os.close( 0 )
      os.open( "/dev/null", os.O_RDONLY )

   global serviceName
   serviceName = args.serviceName
   server = ":/fastclient/" + serviceName

   # clean up environment variables that interfere
   for i in ['COLUMNS','TERM']:
      os.environ.pop( i, None )

   if args.pidfile:
      # pylint: disable-next=consider-using-with,consider-using-f-string
      open( args.pidfile, "w+", 1 ).write( "%d\n" % os.getpid() )

   # This call never exits, but it is like a fork.  The child process
   # returns from it, but the parent never does.  The file descriptor
   # returned is connected to the front-end.
   # pylint: disable-next=c-extension-no-member
   fd = FastServ.serve( "fastserv", server, namespaceFlags )
   after(fd, namespaceFlags)

def after(fd, namespaceFlags):
   argv = FastServUtil.processEnvArgs( fd )
   argv = FastServUtil.popEnvFromArgv( argv )

   if namespaceFlags:
      os.environ['NSNAME'] = serviceName

   if not argv:
      argv = [ os.environ.get('SHELL','bash') ]

   if argv[0] != '-c':
      try:
         if pythonMode:
            exe = Ark.findInPath( argv[0], 'PATH', os.X_OK )
            isPython=False
            try:
               fp = open( exe, 'rb' ) # pylint: disable=consider-using-with
               first128 = fp.read(128)
               fp.close()
               if b'python' in first128:
                  isPython=True
            except: # pylint: disable=bare-except
               pass
            if not isPython:
               os.execl( exe, *argv )
         else:
            os.execlp( argv[0], *argv )
      except ValueError:
         print( "fastserv: executable not found:", argv[0] )
         sys.exit(255)
      else:
         argv[0] = exe
   doArgv( argv )

if __name__ == "__main__":
   main()
