Salome HOME
Merge branch 'eap/23514'
[modules/kernel.git] / bin / salomeContext.py
index 37f181a73a38a66c3db4e5d58e67dbd62bdae1b7..b67209092e82ac095f26d1542f5f7af2d06a5fed 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2013-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2013-2017  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,6 @@ import logging
 import ConfigParser
 
 from parseConfigFile import parseConfigFile
-from parseConfigFile import convertEnvFileToConfigFile
 
 import tempfile
 import pickle
@@ -31,89 +30,107 @@ import subprocess
 import platform
 
 from salomeContextUtils import SalomeContextException
-from salomeContextUtils import getScriptsAndArgs, formatScriptsAndArgs
 
 def usage():
-  #exeName = os.path.splitext(os.path.basename(__file__))[0]
-
   msg = '''\
-Usage: salome [command] [options] [--config=file1,...,filen]
+Usage: salome [command] [options] [--config=<file,folder,...>]
 
 Commands:
-    start         Launches SALOME virtual application [DEFAULT]
-    shell         Executes a script under SALOME application environment
-    connect       Connects a Python console to the active SALOME session
-    killall       Kill all SALOME running sessions
-    info          Display some information about SALOME
-    help          Show this message
-    coffee        Yes! SALOME can also make coffee!!"
-
-Use salome start --help or salome shell --help
-to show help on start and shell commands.
+=========
+    start           Start a new SALOME instance.
+    context         Initialize SALOME context. Current environment is extended.
+    shell           Initialize SALOME context, attached to the last created SALOME
+                    instance if any, and executes scripts passed as command arguments.
+                    User works in a Shell terminal. SALOME environment is set but
+                    application is not started.
+    connect         Connect a Python console to the active SALOME instance.
+    kill <port(s)>  Terminate SALOME instances running on given ports for current user.
+                    Port numbers must be separated by blank characters.
+    killall         Terminate *all* SALOME running instances for current user.
+                    Do not start a new one.
+    test            Run SALOME tests.
+    info            Display some information about SALOME.
+    doc <module(s)> Show online module documentation (if available).
+                    Module names must be separated by blank characters.
+    help            Show this message.
+
+If no command is given, default is start.
+
+Command options:
+================
+    Use salome <command> --help to show help on command. Available for the
+    following commands: start, shell, connect, test, info.
+
+--config=<file,folder,...>
+==========================
+    Initialize SALOME context from a list of context files and/or a list
+    of folders containing context files. The list is comma-separated, whithout
+    any blank characters.
 '''
 
   print msg
 #
 
 """
-The SalomeContext class in an API to configure SALOME environment then
+The SalomeContext class in an API to configure SALOME context then
 start SALOME using a single python command.
 
 """
 class SalomeContext:
   """
-  Initialize environment from a list of configuration files
+  Initialize context from a list of configuration files
   identified by their names.
-  These files should be in appropriate (new .cfg) format.
-  However you can give old .sh environment files; in this case,
-  the SalomeContext class will try to automatically convert them
-  to .cfg format before setting the environment.
+  These files should be in appropriate .cfg format.
   """
-  def __init__(self, configFileNames=[]):
-    #it could be None explicitely (if user use multiples setVariable...for standalone)
-    if configFileNames==None:
+  def __init__(self, configFileNames=0):
+    self.getLogger().setLevel(logging.INFO)
+    #it could be None explicitly (if user use multiples setVariable...for standalone)
+    if configFileNames is None:
        return
-
+    configFileNames = configFileNames or []
     if len(configFileNames) == 0:
       raise SalomeContextException("No configuration files given")
 
-    reserved=['PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH']
+    reserved=['PATH', 'DYLD_FALLBACK_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'MANPATH', 'PV_PLUGIN_PATH', 'INCLUDE', 'LIBPATH', 'SALOME_PLUGINS_PATH', 'LIBRARY_PATH', 'QT_PLUGIN_PATH']
     for filename in configFileNames:
       basename, extension = os.path.splitext(filename)
       if extension == ".cfg":
-        self.__setEnvironmentFromConfigFile(filename, reserved)
-      elif extension == ".sh":
-        #new convert procedures, temporary could be use not to be automatically deleted
-        #temp = tempfile.NamedTemporaryFile(suffix='.cfg', delete=False)
-        temp = tempfile.NamedTemporaryFile(suffix='.cfg')
-        try:
-          convertEnvFileToConfigFile(filename, temp.name, reserved)
-          self.__setEnvironmentFromConfigFile(temp.name, reserved)
-        except ConfigParser.ParsingError, e:
-          self.getLogger().warning("Invalid token found when parsing file: %s\n"%(filename))
-          print e
-          print '\n'
-        finally:
-          # Automatically cleans up the file
-          temp.close()
+        self.__setContextFromConfigFile(filename, reserved)
       else:
-        self.getLogger().warning("Unrecognized extension for configuration file: %s", filename)
+        self.getLogger().error("Unrecognized extension for configuration file: %s", filename)
+  #
+
+  def __loadEnvModules(self, env_modules):
+    print("Trying to load env modules: %s..." % ' '.join(env_modules))
+    try:
+      out, err = subprocess.Popen(["modulecmd", "python", "load"] + env_modules, stdout=subprocess.PIPE).communicate()
+      exec(out) # define specific environment variables
+      print("OK")
+    except:
+      print("** Failed **")
+      pass
   #
 
   def runSalome(self, args):
+    import os
     # Run this module as a script, in order to use appropriate Python interpreter
-    # according to current path (initialized from environment files).
-    kill = False
-    for e in args:
-      if "--shutdown-server" in e:
-        kill = True
-        args.remove(e)
+    # according to current path (initialized from context files).
+    env_modules_option = "--with-env-modules="
+    env_modules_l = [x for x in args if x.startswith(env_modules_option)]
+    if env_modules_l:
+      env_modules = env_modules_l[-1][len(env_modules_option):].split(',')
+      self.__loadEnvModules(env_modules)
+      args = [x for x in args if not x.startswith(env_modules_option)]
+    else:
+      env_modules = os.getenv("SALOME_ENV_MODULES", None)
+      if env_modules:
+        self.__loadEnvModules(env_modules.split(','))
 
     absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
-    proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self),  pickle.dumps(args)], shell=False, close_fds=True)
-    proc.communicate()
-    if kill:
-      self._killAll(args)
+    env_copy = os.environ.copy()
+    proc = subprocess.Popen(['python', os.path.join(absoluteAppliPath,"bin","salome","salomeContext.py"), pickle.dumps(self), pickle.dumps(args)], shell=False, close_fds=True, env=env_copy)
+    out, err = proc.communicate()
+    return out, err, proc.returncode
   #
 
   """Append value to PATH environment variable"""
@@ -123,7 +140,20 @@ class SalomeContext:
 
   """Append value to LD_LIBRARY_PATH environment variable"""
   def addToLdLibraryPath(self, value):
-    self.addToVariable('LD_LIBRARY_PATH', value)
+    if platform.system() == 'Windows':
+      self.addToVariable('PATH', value)
+    elif platform.system() == 'Darwin':
+      if "LAPACK" in value:
+        self.addToVariable('DYLD_FALLBACK_LIBRARY_PATH', value)
+      else:
+        self.addToVariable('DYLD_LIBRARY_PATH', value)
+    else:
+      self.addToVariable('LD_LIBRARY_PATH', value)
+  #
+
+  """Append value to DYLD_LIBRARY_PATH environment variable"""
+  def addToDyldLibraryPath(self, value):
+    self.addToVariable('DYLD_LIBRARY_PATH', value)
   #
 
   """Append value to PYTHONPATH environment variable"""
@@ -135,11 +165,11 @@ class SalomeContext:
   def setVariable(self, name, value, overwrite=False):
     env = os.getenv(name, '')
     if env and not overwrite:
-      self.getLogger().warning("Environment variable already existing (and not overwritten): %s=%s", name, value)
+      self.getLogger().error("Environment variable already existing (and not overwritten): %s=%s", name, value)
       return
 
     if env:
-      self.getLogger().warning("Overwriting environment variable: %s=%s", name, value)
+      self.getLogger().debug("Overwriting environment variable: %s=%s", name, value)
 
     value = os.path.expandvars(value) # expand environment variables
     self.getLogger().debug("Set environment variable: %s=%s", name, value)
@@ -178,13 +208,18 @@ class SalomeContext:
     options = args[1:]
 
     availableCommands = {
-      'start' :   '_runAppli',
-      'shell' :   '_runSession',
+      'start'   : '_runAppli',
+      'context' : '_setContext',
+      'shell'   : '_runSession',
       'connect' : '_runConsole',
-      'killall':  '_killAll',
-      'info':     '_showInfo',
-      'help':     '_usage',
-      'coffee' :  '_makeCoffee'
+      'kill'    : '_kill',
+      'killall' : '_killAll',
+      'test'    : '_runTests',
+      'info'    : '_showInfo',
+      'doc'     : '_showDoc',
+      'help'    : '_usage',
+      'coffee'  : '_makeCoffee',
+      'car'     : '_getCar',
       }
 
     if not command in availableCommands.keys():
@@ -196,120 +231,169 @@ class SalomeContext:
 
   """
   Run SALOME!
-  Args consist in a mandatory command followed by optionnal parameters.
+  Args consist in a mandatory command followed by optional parameters.
   See usage for details on commands.
   """
   def _startSalome(self, args):
+    import os
+    import sys
+    try:
+      from setenv import add_path
+      absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
+      path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome"))
+      add_path(path, "PYTHONPATH")
+      path = os.path.realpath(os.path.join(absoluteAppliPath, "bin", "salome", "appliskel"))
+      add_path(path, "PYTHONPATH")
+
+    except:
+      pass
+
     command, options = self.__parseArguments(args)
     sys.argv = options
 
     if command is None:
       if args and args[0] in ["-h","--help","help"]:
         usage()
-        sys.exit(0)
+        return 0
       # try to default to "start" command
       command = "_runAppli"
 
     try:
       res = getattr(self, command)(options) # run appropriate method
-      return res or (None, None)
-    except SystemExit, exc:
-      if exc==0:
-        sys.exit(0) #catch sys.exit(0) happy end no warning
-      if exc==1:
-        self.getLogger().warning("SystemExit 1 in method %s.", command)
-      sys.exit(1)
+      return res or 0
+    except SystemExit as ex:
+      if ex.code != 0:
+        self.getLogger().error("SystemExit %s in method %s.", ex.code, command)
+      return ex.code
     except StandardError:
       self.getLogger().error("Unexpected error:")
       import traceback
       traceback.print_exc()
-      sys.exit(1)
+      return 1
     except SalomeContextException, e:
       self.getLogger().error(e)
-      sys.exit(1)
+      return 1
   #
 
-  def __setEnvironmentFromConfigFile(self, filename, reserved=[]):
-    unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+  def __setContextFromConfigFile(self, filename, reserved=None):
+    if reserved is None:
+      reserved = []
+    try:
+      unsetVars, configVars, reservedDict = parseConfigFile(filename, reserved)
+    except SalomeContextException, e:
+      msg = "%s"%e
+      self.getLogger().error(msg)
+      return 1
 
     # unset variables
     for var in unsetVars:
       self.unsetVariable(var)
 
-    # set environment
+    # set context
     for reserved in reservedDict:
       a = filter(None, reservedDict[reserved]) # remove empty elements
-      reformattedVals = ':'.join(a)
-      self.addToVariable(reserved, reformattedVals)
+      a = [ os.path.realpath(x) for x in a ]
+      reformattedVals = os.pathsep.join(a)
+      if reserved in ["INCLUDE", "LIBPATH"]:
+        self.addToVariable(reserved, reformattedVals, separator=' ')
+      else:
+        self.addToVariable(reserved, reformattedVals)
       pass
 
     for key,val in configVars:
       self.setVariable(key, val, overwrite=True)
       pass
 
-    sys.path[:0] = os.getenv('PYTHONPATH','').split(':')
+    pythonpath = os.getenv('PYTHONPATH','').split(os.pathsep)
+    pythonpath = [ os.path.realpath(x) for x in pythonpath ]
+    sys.path[:0] = pythonpath
   #
 
-  def _runAppli(self, args=[]):
+  def _runAppli(self, args=None):
+    if args is None:
+      args = []
     # Initialize SALOME environment
     sys.argv = ['runSalome'] + args
     import setenv
-    setenv.main(True)
+    setenv.main(True, exeName="salome start")
 
     import runSalome
     runSalome.runSalome()
+    return 0
   #
 
-  def _runSession(self, args=[]):
+  def _setContext(self, args=None):
+    salome_context_set = os.getenv("SALOME_CONTEXT_SET")
+    if salome_context_set:
+      print "***"
+      print "*** SALOME context has already been set."
+      print "*** Enter 'exit' (only once!) to leave SALOME context."
+      print "***"
+      return 0
+
+    os.environ["SALOME_CONTEXT_SET"] = "yes"
+    print "***"
+    print "*** SALOME context is now set."
+    print "*** Enter 'exit' (only once!) to leave SALOME context."
+    print "***"
+
+    cmd = ["/bin/bash"]
+    proc = subprocess.Popen(cmd, shell=False, close_fds=True)
+    proc.communicate()
+    return proc.returncode
+  #
+
+  def _runSession(self, args=None):
+    if args is None:
+      args = []
     sys.argv = ['runSession'] + args
     import runSession
-    runSession.configureSession(args)
+    params, args = runSession.configureSession(args, exe="salome shell")
 
+    sys.argv = ['runSession'] + args
     import setenv
     setenv.main(True)
 
-    scriptArgs = getScriptsAndArgs(args)
-    command = formatScriptsAndArgs(scriptArgs)
-    if command:
-      sep = ";"
-      if sys.platform == "win32":
-        sep= "&"
-      command = command.split(sep)
-      outmsg = []
-      errmsg = []
-      for cmd in command:
-        cmd = cmd.strip().split(' ')
-        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        (stdoutdata, stderrdata) = proc.communicate()
-        if stdoutdata or stderrdata:
-          outmsg.append(stdoutdata)
-          errmsg.append(stderrdata)
-
-      return ("".join(outmsg), "".join(errmsg))
-    else:
-      absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
-      cmd = ["/bin/bash",  "--rcfile", absoluteAppliPath + "/.bashrc" ]
-      proc = subprocess.Popen(cmd, shell=False, close_fds=True)
-      proc.wait()
+    return runSession.runSession(params, args)
   #
 
-  def _runConsole(self, args=[]):
+  def _runConsole(self, args=None):
+    if args is None:
+      args = []
     # Initialize SALOME environment
-    sys.argv = ['runConsole'] + args
+    sys.argv = ['runConsole']
     import setenv
     setenv.main(True)
 
     import runConsole
-    runConsole.connect()
+    return runConsole.connect(args)
   #
 
-  def _killAll(self, args=[]):
-    absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH','')
+  def _kill(self, args=None):
+    if args is None:
+      args = []
+    ports = args
+    if not ports:
+      print "Port number(s) not provided to command: salome kill <port(s)>"
+      return 1
+
+    from multiprocessing import Process
+    from killSalomeWithPort import killMyPort
+    import tempfile
+    for port in ports:
+      with tempfile.NamedTemporaryFile():
+        p = Process(target = killMyPort, args=(port,))
+        p.start()
+        p.join()
+    return 0
+  #
+
+  def _killAll(self, unused=None):
     try:
       import PortManager # mandatory
       from multiprocessing import Process
       from killSalomeWithPort import killMyPort
-      ports = PortManager.getBusyPorts()
+      ports = PortManager.getBusyPorts()['this']
 
       if ports:
         import tempfile
@@ -318,27 +402,139 @@ class SalomeContext:
             p = Process(target = killMyPort, args=(port,))
             p.start()
             p.join()
-
-      p = Process(target = killMyPort, args=(2809,))
-      p.start()
-      p.join()
     except ImportError:
+      # :TODO: should be declared obsolete
       from killSalome import killAllPorts
       killAllPorts()
       pass
+    return 0
+  #
 
+  def _runTests(self, args=None):
+    if args is None:
+      args = []
+    sys.argv = ['runTests']
+    import setenv
+    setenv.main(True)
+
+    import runTests
+    return runTests.runTests(args, exe="salome test")
   #
 
-  def _showInfo(self, args=[]):
-    print "Running with python", platform.python_version()
-    self._runAppli(["--version"])
+  def _showSoftwareVersions(self, softwares=None):
+    config = ConfigParser.SafeConfigParser()
+    absoluteAppliPath = os.getenv('ABSOLUTE_APPLI_PATH')
+    filename = os.path.join(absoluteAppliPath, "sha1_collections.txt")
+    versions = {}
+    max_len = 0
+    with open(filename) as f:
+      for line in f:
+        try:
+          software, version, sha1 = line.split()
+          versions[software.upper()] = version
+          if len(software) > max_len:
+            max_len = len(software)
+        except:
+          pass
+        pass
+      pass
+    if softwares:
+      for soft in softwares:
+        if versions.has_key(soft.upper()):
+          print soft.upper().rjust(max_len), versions[soft.upper()]
+    else:
+      import collections
+      od = collections.OrderedDict(sorted(versions.items()))
+      for name, version in od.iteritems():
+        print name.rjust(max_len), versions[name]
+    pass
+
+  def _showInfo(self, args=None):
+    if args is None:
+      args = []
+
+    usage = "Usage: salome info [options]"
+    epilog  = """\n
+Display some information about SALOME.\n
+Available options are:
+    -p,--ports                     Show the list of busy ports (running SALOME instances).
+    -s,--softwares [software(s)]   Show the list and versions of SALOME softwares.
+                                   Software names must be separated by blank characters.
+                                   If no software is given, show version of all softwares.
+    -v,--version                   Show running SALOME version.
+    -h,--help                      Show this message.
+"""
+    if not args:
+      args = ["--version"]
+
+    if "-h" in args or "--help" in args:
+      print usage + epilog
+      return 0
+
+    if "-p" in args or "--ports" in args:
+      import PortManager
+      ports = PortManager.getBusyPorts()
+      this_ports = ports['this']
+      other_ports = ports['other']
+      if this_ports or other_ports:
+          print "SALOME instances are running on the following ports:"
+          if this_ports:
+              print "   This application:", this_ports
+          else:
+              print "   No SALOME instances of this application"
+          if other_ports:
+              print "   Other applications:", other_ports
+          else:
+              print "   No SALOME instances of other applications"
+      else:
+          print "No SALOME instances are running"
+
+    if "-s" in args or "--softwares" in args:
+      if "-s" in args:
+        index = args.index("-s")
+      else:
+        index = args.index("--softwares")
+      indexEnd=index+1
+      while indexEnd < len(args) and args[indexEnd][0] != "-":
+        indexEnd = indexEnd + 1
+      self._showSoftwareVersions(softwares=args[index+1:indexEnd])
+
+    if "-v" in args or "--version" in args:
+      print "Running with python", platform.python_version()
+      return self._runAppli(["--version"])
+
+    return 0
   #
 
-  def _usage(self, unused=[]):
+  def _showDoc(self, args=None):
+    if args is None:
+      args = []
+
+    modules = args
+    if not modules:
+      print "Module(s) not provided to command: salome doc <module(s)>"
+      return 1
+
+    appliPath = os.getenv("ABSOLUTE_APPLI_PATH")
+    if not appliPath:
+      raise SalomeContextException("Unable to find application path. Please check that the variable ABSOLUTE_APPLI_PATH is set.")
+    baseDir = os.path.join(appliPath, "share", "doc", "salome")
+    for module in modules:
+      docfile = os.path.join(baseDir, "gui", module.upper(), "index.html")
+      if not os.path.isfile(docfile):
+        docfile = os.path.join(baseDir, "tui", module.upper(), "index.html")
+      if not os.path.isfile(docfile):
+        docfile = os.path.join(baseDir, "dev", module.upper(), "index.html")
+      if os.path.isfile(docfile):
+        out, err = subprocess.Popen(["xdg-open", docfile]).communicate()
+      else:
+        print "Online documentation is not accessible for module:", module
+
+  def _usage(self, unused=None):
     usage()
   #
 
-  def _makeCoffee(self, args=[]):
+  def _makeCoffee(self, unused=None):
     print "                        ("
     print "                          )     ("
     print "                   ___...(-------)-....___"
@@ -349,9 +545,9 @@ class SalomeContext:
     print "       |  |    |                             |"
     print "        \\  \\   |                             |"
     print "         `\\ `\\ |                             |"
-    print "           `\\ `|                             |"
-    print "           _/ /\\                             /"
-    print "          (__/  \\                           /"
+    print "           `\\ `|            SALOME           |"
+    print "           _/ /\\            4 EVER           /"
+    print "          (__/  \\             <3            /"
     print "       _..---\"\"` \\                         /`\"\"---.._"
     print "    .-\'           \\                       /          \'-."
     print "   :               `-.__             __.-\'              :"
@@ -361,7 +557,42 @@ class SalomeContext:
     print "       \'._     \"\"\"----.....______.....----\"\"\"     _.\'"
     print "          `\"\"--..,,_____            _____,,..--\"\"`"
     print "                        `\"\"\"----\"\"\"`"
-    sys.exit(0)
+    print ""
+    print "                    SALOME is working for you; what else?"
+    print ""
+  #
+
+  def _getCar(self, unused=None):
+    print "                                              _____________"
+    print "                                  ..---:::::::-----------. ::::;;."
+    print "                               .\'\"\"\"\"\"\"                  ;;   \\  \":."
+    print "                            .\'\'                          ;     \\   \"\\__."
+    print "                          .\'                            ;;      ;   \\\\\";"
+    print "                        .\'                              ;   _____;   \\\\/"
+    print "                      .\'                               :; ;\"     \\ ___:\'."
+    print "                    .\'--...........................    : =   ____:\"    \\ \\"
+    print "               ..-\"\"                               \"\"\"\'  o\"\"\"     ;     ; :"
+    print "          .--\"\"  .----- ..----...    _.-    --.  ..-\"     ;       ;     ; ;"
+    print "       .\"\"_-     \"--\"\"-----\'\"\"    _-\"        .-\"\"         ;        ;    .-."
+    print "    .\'  .\'   SALOME             .\"         .\"              ;       ;   /. |"
+    print "   /-./\'         4 EVER <3    .\"          /           _..  ;       ;   ;;;|"
+    print "  :  ;-.______               /       _________==.    /_  \\ ;       ;   ;;;;"
+    print "  ;  / |      \"\"\"\"\"\"\"\"\"\"\".---.\"\"\"\"\"\"\"          :    /\" \". |;       ; _; ;;;"
+    print " /\"-/  |                /   /                  /   /     ;|;      ;-\" | ;\';"
+    print ":-  :   \"\"\"----______  /   /              ____.   .  .\"\'. ;;   .-\"..T\"   ."
+    print "\'. \"  ___            \"\":   \'\"\"\"\"\"\"\"\"\"\"\"\"\"\"    .   ; ;    ;; ;.\" .\"   \'--\""
+    print " \",   __ \"\"\"  \"\"---... :- - - - - - - - - \' \'  ; ;  ;    ;;\"  .\""
+    print "  /. ;  \"\"\"---___                             ;  ; ;     ;|.\"\""
+    print " :  \":           \"\"\"----.    .-------.       ;   ; ;     ;:"
+    print "  \\  \'--__               \\   \\        \\     /    | ;     ;;"
+    print "   \'-..   \"\"\"\"---___      :   .______..\\ __/..-\"\"|  ;   ; ;"
+    print "       \"\"--..       \"\"\"--\"        m l s         .   \". . ;"
+    print "             \"\"------...                  ..--\"\"      \" :"
+    print "                        \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"    \\        /"
+    print "                                               \"------\""
+    print ""
+    print "                                Drive your simulation properly with SALOME!"
+    print ""
   #
 
   # Add the following two methods since logger is not pickable
@@ -380,21 +611,18 @@ class SalomeContext:
     if not hasattr(self, '_logger'):
       self._logger = logging.getLogger(__name__)
       #self._logger.setLevel(logging.DEBUG)
+      #self._logger.setLevel(logging.WARNING)
       self._logger.setLevel(logging.ERROR)
     return self._logger
   #
 
-###
-import pickle
 if __name__ == "__main__":
   if len(sys.argv) == 3:
     context = pickle.loads(sys.argv[1])
     args = pickle.loads(sys.argv[2])
-    (out, err) = context._startSalome(args)
-    if out:
-      sys.stdout.write(out)
-    if err:
-      sys.stderr.write(err)
+
+    status = context._startSalome(args)
+    sys.exit(status)
   else:
     usage()
 #