Salome HOME
Add message that batch mode is unavailable in current version of IW.
[tools/install.git] / runInstall
index 4a4796f8ec9d49e96befea1d3991293ccbfef473..37bb8a29603aad73e3e37b10697022146cfe4c21 100755 (executable)
 #!/usr/bin/env python
 
+"""
+Installation Wizard launching script.
+
+This script is the part of the SALOME installation procedure.
+Author    : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com)
+Created   : Thu Dec 18 12:01:00 2002
+Copyright : 2002-2007 CEA
+
+"""
+
+__version__ = "1.0.1"
+
+# --- avoid "deprecation" warnings --- #
 import warnings
 warnings.filterwarnings("ignore", "", DeprecationWarning)
 
+# --- imports --- #
 import xmllib
-import sys, os, string, re
-from optparse import OptionParser
+import sys, os, re
+import types
+import random
 
+# --- global variables --- #
 opt_parser = None
 root_path  = None
 
+# --- XML tags definition --- #
 __TAG__SOURCES__    = "install sources"
 __TAG__BINARIES__   = "install binaries"
 __TAG__NATIVE__     = "use native"
 __TAG__PREINSTALL__ = "not install"
+__TAG__BUILDSRC__   = "build sources"
+
+# --- product context definition --- #
+__CTX__SALOME__SRC__  = "salome sources"
+__CTX__SALOME__BIN__  = "salome binaries"
+__CTX__PREREQUISITE__ = "prerequisite"
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                 COMMAND LINE ARGUMENTS PARSER                    #
+#                                                                  #
+#------------------------------------------------------------------#
+
+#===================================================================
+# class OptBaseError : base parse error
+#===================================================================
+class OptBaseError(Exception):
+    """
+    Base option parsing exception class
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__ (self):
+        return self.msg
+
+#===================================================================
+# class OptError : bad option error
+#===================================================================
+class OptError(OptBaseError):
+    """
+    Bad option exception class
+    """
+    def __init__ (self, msg, option):
+        self.msg = msg
+        self.option = option
+    def __str__ (self):
+        if self.option:
+            opt_prs = "<unknown>"
+            if self.option.short_opt and self.option.long_opt:
+                opt_prs = "%s/%s"%(self.option.short_opt,self.option.long_opt)
+            elif self.option.short_opt:
+                opt_prs = "%s"%(self.option.short_opt)
+            elif self.option.long_opt:
+                opt_prs = "%s"%(self.option.long_opt)
+            return "option %s: %s"%(opt_prs, self.msg)
+        return self.msg
+
+#===================================================================
+# class ArgError : bad option argument error
+#===================================================================
+class ArgError(OptBaseError):
+    """
+    Bad argument exception class
+    """
+    pass
+
+#===================================================================
+# class ValError : bad command line parameter error
+#===================================================================
+class ValError(OptBaseError):
+    """
+    Bad parameter exception class
+    """
+    pass
+
+#===================================================================
+# class ArgOption : command line option
+#===================================================================
+class ArgOption:
+    """
+    Option class
+    """
+    attrs   = ["short_opt", "long_opt", "dest", "action", "type", "default", "metavar", "help"]
+    actions = ["store", "store_true", "store_false"]
+    types   = ["string", "int", "float", "bool"]
+    def __init__(self, *args, **kwargs):
+        # set defaults
+        for attr in self.attrs: setattr(self, attr, None)
+        # parse arguments
+        for i in range(len(args)):
+            if i > len(self.attrs)-1:
+                msg = "Wrong number of parameters is given (maximum is %d)" % len(self.attrs)
+                raise OptBaseError(msg)
+            setattr(self, self.attrs[i], args[i])
+        for arg in kwargs:
+            if arg not in self.attrs:
+                msg = "Invalid argument: %s" % arg
+                raise OptBaseError(msg)
+            setattr(self, arg, kwargs[arg])
+        # check short option key
+        if self.short_opt and \
+               not re.match("^-[a-zA-Z]$",self.short_opt):
+            msg  = "invalid short option key; "
+            msg += "should be of the form -x (x is letter)"
+            raise OptError(msg, self)
+        # check long option key
+        if self.long_opt and \
+               not re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$",self.long_opt):
+            msg  = "invalid long option key; "
+            msg += "should be of the form --word[[-word]...] "
+            msg += "(word is letters and digits sequence)"
+            raise OptError(msg, self)
+        # check that at least one option key is defined
+        if not self.short_opt and not self.long_opt:
+            msg  = "invalid option; neither short nor long option key is defined"
+            raise OptError(msg, self)
+        # destination
+        if not self.dest and self.long_opt:
+            self.dest = self.long_opt[2:].replace('-','_')
+        if not self.dest and self.short_opt:
+            self.dest = self.short_opt[1:]
+        # action
+        if not self.action:
+            self.action = "store"
+        if self.action not in self.actions:
+            msg  = "invalid action: %s" % self.action
+            raise OptError(msg, self)
+        # type
+        if not self.type:
+            if self.action in ["store_true","store_false"]: self.type = "bool"
+            else: self.type = "string"
+        if self.type not in self.types:
+            msg  = "invalid type: %s" % self.type
+            raise OptError(msg, self)
+        if self.action in ["store_true","store_false"] and self.type != "bool":
+            msg  = "invalid type: %s : should be 'bool' or None" % self.type
+            raise OptError(msg, self)
+        # default
+        if self.default:
+            try:
+                if self.type == "string": self.default = str(self.default)
+                if self.type == "int":    self.default = int(self.default)
+                if self.type == "float":  self.default = float(self.default)
+                if self.type == "bool":   self.default = boolean(self.default)
+            except :
+                msg  = "invalid default value type: should be %s" % self.type
+                raise OptError(msg, self)
+            pass
+        # metavar
+        if not self.metavar:
+            self.metavar = self.dest.upper()
+        # help
+        if not self.help:
+            self.help = ""
+        pass
+
+    def to_string(self):
+        """
+        Returns string representation of the option
+        """
+        opts = []
+        opt = self.short_opt
+        if opt and self.action == "store" and self.metavar: opt += " %s" % self.metavar
+        if opt: opts.append(opt)
+        opt = self.long_opt
+        if opt and self.action == "store" and self.metavar: opt += "=%s" % self.metavar
+        if opt: opts.append(opt)
+        return (", ").join(opts)
+    
+#===================================================================
+# class Values : resulting option values
+#===================================================================
+class Values:
+    """
+    Values class
+    """
+    def __init__(self):
+        pass
+        
+#===================================================================
+# class ArgParser : command line arguments parser
+#===================================================================
+class ArgParser:
+    """
+    Arguments parser class
+    """
+    def __init__(self):
+        self.options = []
+        pass
 
+    def add_option(self, *args, **kwargs):
+        """Register an option"""
+        o = ArgOption(*args, **kwargs)
+        self._check_option(o)
+        self.options.append(o)
+        pass
+
+    def parse_args(self, args = None):
+        """Parse an arguments"""
+        if not args: args = sys.argv[1:]
+        values = Values()
+        for o in self.options:
+            if o.default:
+                setattr(values, o.dest, o.default)
+            elif not hasattr(values,o.dest):
+                setattr(values, o.dest, None)
+        try:
+            (values, args) = self._process_args(values, args)
+        except (ArgError, ValError), e:
+            self._error(e.msg)
+
+        return (values, args)
+            
+    def print_usage(self):
+        """Print usage"""
+        print "usage: %s [options]" % os.path.basename(sys.argv[0])
+        pass
+
+    def print_help(self):
+        """Print help"""
+        self.print_usage()
+        print ""
+        olen = 0
+        _maxwidth, _indent = 79, 2
+        if len(self.options):
+            for option in self.options:
+                if olen < len(option.to_string()): olen = len(option.to_string())
+            print "options:"
+            for option in self.options:
+                strings = []
+                for hs in option.help.split("\n"):
+                    s = ""
+                    for w in hs.split():
+                        if len("%s %s" % (s,w)) > _maxwidth:
+                            strings.append(s.strip()); s = ""
+                        s = "%s %s" % (s,w)
+                    if s.strip(): strings.append(s.strip())
+                if not strings: strings[:0] = [""]
+                print "%s%s%s" % (option.to_string(), " "*(_indent+olen-len(option.to_string())), strings[0])
+                for i in range(1, len(strings)):
+                    print "%s%s" % (" "*(olen+_indent), strings[i])
+        pass
+    
+    def _check_option(self, option):
+        o = self._get_option(option.short_opt)
+        if not o: o = self._get_option(option.long_opt)
+        if o:
+            msg = "option conflicts with previously defined option(s)"
+            raise OptError(msg, option)
+        pass
+
+    def _get_option(self, opt_key):
+        if opt_key:
+            for o in self.options:
+                if opt_key in [o.short_opt, o.long_opt]: return o
+        return None
+        
+    def _error(self, msg):
+        self.print_usage()
+        sys.exit("\n%s: error: %s\n" % (os.path.basename(sys.argv[0]), msg))
+        pass
+
+    def _check_value(self, option, value):
+        o = self._get_option(option)
+        try:
+            if o.type == "string": return str(value)
+            if o.type == "int":    return int(value)
+            if o.type == "float":  return float(value)
+            if o.type == "bool":   return boolean(value)
+        except:
+            msg  = "invalid value type for option %s: %s; " % (option, value)
+            msg += "should be %s" % o.type
+            raise ValError(msg)
+        raise OptBaseError("unknown error")
+
+    def _process_args(self, values, args):
+        res_args = []
+        cur_opt = None
+        rargs   = []
+        for index in range(len(args)):
+            a = args[index]
+            if cur_opt and cur_opt[1].action == "store":
+                setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a))
+                cur_opt = None
+                continue
+            if a == "-":
+                rargs = args[index+1:]
+                break
+            elif re.match("^-[a-zA-Z].*", a):
+                for i in range(1,len(a)):
+                    if cur_opt and cur_opt[1].action == "store":
+                        setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a[i:]))
+                        cur_opt = None
+                        break
+                    o = self._get_option("-%s"%a[i])
+                    if not o:
+                        raise ArgError("no such option: -%s"%a[i])
+                    if o.action == "store_true":
+                        setattr(values, o.dest, True)
+                    elif o.action == "store_false":
+                        setattr(values, o.dest, False)
+                    else:
+                        cur_opt = ("-%s"%a[i], o)
+                pass
+            elif re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*", a):
+                oname  = ("%s="%a).split("=")[0]
+                ovalue = ("%s="%a).split("=")[1]
+                o = self._get_option(oname)
+                if not o:
+                    raise ArgError("no such option: %s" % oname)
+                if o.action == "store_true":
+                    if ovalue:
+                        raise ValError("option %s does not take a value" % oname)
+                    setattr(values, o.dest, True)
+                elif o.action == "store_false":
+                    if ovalue:
+                        raise ValError("option %s does not take a value" % oname)
+                    setattr(values, o.dest, False)
+                else:
+                    if ovalue:
+                        setattr(values, o.dest, self._check_value(oname, ovalue))
+                    else:
+                        cur_opt = (oname, o)
+                pass
+            elif a.startswith("-"):
+                raise ArgError("bad formatted option: %s" % a)
+            else:
+                rargs = args[index:]
+                break
+        if cur_opt and cur_opt[1].action == "store":
+            raise ValError("option %s requires value" % cur_opt[0])
+        return (values, rargs)
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                 XML CONFIGURATION FILES PARSER                   #
+#                                                                  #
+#------------------------------------------------------------------#
+
+#===================================================================
+# class Config : general configuration options : version, target and
+#                temporary directories, etc...
+#===================================================================
+class Config :
+    """
+    General configuration file options:
+    - Install Wizard window caption
+    - SALOME platform version
+    - Copyright and license info
+    - Default target and temporary directories
+    """
+    def __init__(self,
+                 theVersion   = None,
+                 theCaption   = None,
+                 theCopyright = None,
+                 theLicense   = None,
+                 thePlatforms = None,
+                 theTargetdir = None,
+                 theTmpdir    = None):
+        self.version   = strip(theVersion)
+        self.caption   = strip(theCaption)
+        self.copyright = strip(theCopyright)
+        self.license   = strip(theLicense)
+        self.platforms = strip(thePlatforms)
+        self.targetdir = strip(theTargetdir)
+        self.tmpdir    = strip(theTmpdir)
+
+## #===================================================================
+## # class Path : default target, temporary directories options
+## #===================================================================
+## class Path :
+##     """
+##     Path options:
+##     - default target directory
+##     - default temporary directory
+##     """
+##     def __init__(self,
+##                  theTargetdir = None,
+##                  theTmpdir    = None):
+##         self.targetdir = strip(theTargetdir)
+##         self.tmpdir    = strip(theTmpdir)
+        
 #==============================================================
-# class Product 
+# class Product : pre-requisite product options
 #==============================================================
-
 class Product :
+    """
+    Product options:
+    - name, version
+    - target Linux OS version
+    - supported installation modes and the default one
+    - dependencies
+    - required disk space
+    - installation script
+    - etc...
+    """
     def __init__(self,
                  theName,
+                 theType               = None,
+                 theOS                 = None,
                  theVersion            = None,
                  theInstall            = None,
                  theSupportred         = None,
@@ -31,6 +430,8 @@ class Product :
                  theScript             = None,
                  thePickUpEnvironment  = None):
         self.name               = strip(theName)
+        self.type               = strip(theType)
+        self.os                 = strip(theOS)
         self.version            = strip(theVersion)
         self.install            = strip(theInstall)
         self.supported          = strip(theSupportred)
@@ -39,51 +440,71 @@ class Product :
         self.temporarydiskspace = strip(theTemporarydiskspace)
         self.script             = strip(theScript)
         self.pickupEnv          = strip(thePickUpEnvironment)
+        self.whattodo           = self.install
+        
+    def hasContext(self, ctx):
+        try:
+            return ctx in [ strip(s) for s in self.context.split(",") ]
+        except:
+            pass
+        return False
 
-#===================================================================
-# class Config
-#===================================================================
-class Config :
-    def __init__(self,
-                 theVersion   = None,
-                 theCaption   = None,
-                 theCopyright = None,
-                 theLicense   = None,
-                 theOS        = None):
-        self.version   = strip(theVersion)
-        self.caption   = strip(theCaption)
-        self.copyright = strip(theCopyright)
-        self.license   = strip(theLicense)
-        self.os        = strip(theOS)
-
-#===================================================================
-# class Path
-#===================================================================
-class Path :
-    def __init__(self,
-                 theTargetdir = None,
-                 theTmpdir    = None):
-        self.targetdir = strip(theTargetdir)
-        self.tmpdir    = strip(theTmpdir)
+    def setMode(self, mode):
+        if mode not in [__TAG__SOURCES__, __TAG__BINARIES__, __TAG__NATIVE__, __TAG__PREINSTALL__]:
+            return
+        try:
+            supported = [ strip(s) for s in self.supported.split(",") ]
+            if mode in supported or mode == __TAG__PREINSTALL__:
+                self.install = mode
+                self.whattodo = self.install
+            salbin = self.hasContext(__CTX__SALOME__BIN__)
+            salsrc = self.hasContext(__CTX__SALOME__SRC__)
+            if mode == __TAG__SOURCES__:
+                if salbin and not salsrc:
+                    self.install = __TAG__PREINSTALL__
+                    self.whattodo = self.install
+                elif salsrc:
+                    self.whattodo = __TAG__BUILDSRC__
+        except:
+            pass
+        return
         
 #===================================================================
-# class ConfigParser
+# class ConfigParser : XML files parser implementation
 #===================================================================
 class ConfigParser(xmllib.XMLParser):
-    def __init__(self):
+    """
+    XML configuration files parser
+    """
+    def __init__(self, is_force_src=False):
         xmllib.XMLParser.__init__(self)
         self.products = []
         self.currentdata = []
-        self.path = None
+##         self.path = None
         self.config = None
+        self.is_force_src = is_force_src
         
     def handle_data(self, data):
         self.currentdata.append(data)
         
+    def start_config(self, attrs):
+        self.config = Config(attrs.get('version',   None),
+                             attrs.get('caption',   None),
+                             attrs.get('copyright', None),
+                             attrs.get('license',   None),
+                             attrs.get('platforms', None),
+                             attrs.get('targetdir', None),
+                             attrs.get('tempdir',   None))
+        pass
+    
+    def end_config(self):
+        pass
+
     def start_product(self, attrs):
         if not attrs.get('name', '').strip():         return
         if check_bool(attrs.get('disable', 'false')): return
         aProduct = Product(attrs.get('name'),
+                           attrs.get('type',               None),
                            attrs.get('version',            None),
                            attrs.get('install',            None),
                            attrs.get('supported',          None),
@@ -92,30 +513,37 @@ class ConfigParser(xmllib.XMLParser):
                            attrs.get('temporarydiskspace', None),
                            attrs.get('script',             None),
                            attrs.get('pickupenv',          None))
+        if self.is_force_src:
+            aProduct.setMode(__TAG__SOURCES__)
         self.products.append(aProduct)
         pass
 
     def end_product(self):
         pass
 
-    def start_config(self, attrs):
-        self.config = Config(attrs.get('version',   None),
-                             attrs.get('caption',   None),
-                             attrs.get('copyright', None),
-                             attrs.get('license',   None),
-                             attrs.get('os',        None))
+    def start_installation(self, attrs):
+##         anInstallation = Installation(attrs.get('os',                 None),
+##                                       attrs.get('type',               None),
+##                                       attrs.get('version',            None),
+##                                       attrs.get('install',            None),
+##                                       attrs.get('supported',          None),
+##                                       attrs.get('dependancies',       None),
+##                                       attrs.get('installdiskspace',   None),
+##                                       attrs.get('temporarydiskspace', None),
+##                                       attrs.get('script',             None),
+##                                       attrs.get('pickupenv',          None))
         pass
     
-    def end_config(self):
+    def end_installation(self):
         pass
 
-    def start_path (self, attrs):
-        self.path = Path(attrs.get('targetdir', None),
-                         attrs.get('tempdir',   None))
-        pass
+##     def start_path (self, attrs):
+##         self.path = Path(attrs.get('targetdir', None),
+##                          attrs.get('tempdir',   None))
+##         pass
         
-    def end_path(self):
-        pass
+##     def end_path(self):
+##         pass
 
     def getProduct(self, prod):
         for product in self.products:
@@ -123,10 +551,25 @@ class ConfigParser(xmllib.XMLParser):
                 return product
         return None
 
+    def getInstallation(self, os):
+        for product in self.products:
+            if product.name == prod:
+                return product
+        return None
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                         SERVICE FUNCTIONS                        #
+#                                                                  #
+#------------------------------------------------------------------#
+
 #==============================================================
 # message: prints diagnostic information
 #==============================================================
 def message(msg):
+    """
+    Prints diagnostic information.
+    """
     if msg.strip():
         print ">>>", msg
     pass
@@ -135,6 +578,9 @@ def message(msg):
 # warning: prints warning
 #==============================================================
 def warning(msg):
+    """
+    Prints warning.
+    """
     if msg.strip():
         print ""
         print msg
@@ -146,6 +592,10 @@ def warning(msg):
 #              help information and quits
 #==============================================================
 def error_exit(msg = "", print_help = True):
+    """
+    Prints (optionally) error string,
+    then prints help information and quits.
+    """
     # print error message
     if len(msg.strip()):
         print ""
@@ -163,10 +613,40 @@ def error_exit(msg = "", print_help = True):
     sys.exit(1);
     pass
 
+#==============================================================
+# boolean : Converts string to boolean value.
+#==============================================================
+def boolean(val):
+    """
+    Converts string to boolean value if possible.
+    Raises exception if wrong string is used.
+    """
+    if isinstance(val, types.StringType):
+        if val.strip().lower()   in ["true",  "yes", "ok"]     : return True
+        elif val.strip().lower() in ["false", "no",  "cancel"] : return False
+        else: raise TypeError("invalid boolean value")
+    return bool(val)
+
+#=================================================================
+# check_bool : checks boolean value: yes/no, true/false, 1/0
+#=================================================================
+def check_bool(val):
+    """
+    Checks boolean value.
+    """
+    try:
+        return boolean(val)
+    except:
+        pass
+    return False
+
 #==============================================================
 # clean_all : performs system cleaning before exiting
 #==============================================================
 def clean_all():
+    """
+    Performs system cleaning before exiting.
+    """
     global root_path
     remove_dir(root_path)
     pass
@@ -175,18 +655,20 @@ def clean_all():
 # parse_parameters : parses command line arguments
 #==============================================================
 def parse_parameters():
+    """
+    Parses command line arguments.
+    """
     global opt_parser
-    opt_parser = OptionParser(add_help_option=False)
+    opt_parser = ArgParser()
+    
     help_str  = "Runs the Installation Wizard in the GUI mode [default].\n"
-    help_str += "In this case only -f option is taken into account. "
-    help_str += "Other options are ignored."
     opt_parser.add_option("-g",
                           "--gui",
                           action="store_true",
                           dest="gui",
                           default=True,
                           help=help_str)
-    help_str  = "Runs the Installation Wizard in the TUI mode."
+    help_str  = "Runs the Installation Wizard in the TUI mode (UNAVAILABLE NOW)."
     opt_parser.add_option("-b",
                           "--batch",
                           action="store_false",
@@ -195,10 +677,7 @@ def parse_parameters():
     help_str  = "The configuration xml file.\n"
     help_str += "If this parameter is missing, then the program tries to define the "
     help_str += "Linux platform and use the corresponding xml file. For example, "
-    help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case."
-    help_str += "If program fails to define target Linux platform or the corresponding "
-    help_str += "xml file is not provided with the Installation Wizard, then default "
-    help_str += "config.xml file is used."
+    help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case. "
     opt_parser.add_option("-f",
                           "--file",
                           action="store",
@@ -214,7 +693,7 @@ def parse_parameters():
                           dest="target_dir",
                           metavar="DIR",
                           help=help_str)
-    help_str  = "The directory used for temporary files.\n"
+    help_str  = "The directory to be used for temporary files.\n"
     help_str += "When used this parameter overrides the default temporary directory "
     help_str += "defined in the configuration xml file."
     opt_parser.add_option("-t",
@@ -223,12 +702,12 @@ def parse_parameters():
                           dest="tmp_dir",
                           metavar="DIR",
                           help=help_str)
-    help_str  = "Prints this help and quits."
+    help_str  = "Prints version information and quits."
     opt_parser.add_option("-v",
                           "--version",
                           action="store_true",
                           help=help_str)
-    help_str  = "Prints version information and quits."
+    help_str  = "Prints this help and quits."
     opt_parser.add_option("-h",
                           "--help",
                           action="store_true",
@@ -250,34 +729,25 @@ def parse_parameters():
     return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui]
 
 #=================================================================
-# strip : removes spaces at the beginning and at eh end of the 
+# strip : removes spaces at the beginning and at the end of the 
 #         <param> if it is of string type
 #=================================================================
 def strip(param):
-    import types
+    """
+    Removes spaces at the beginning and at the end
+    of the given parameter.
+    """
     if type(param) == types.StringType:
         return param.strip()
     return param
     
-#=================================================================
-# check_bool : checks boolean value: yes/no, true/false, 1/0
-#=================================================================
-def check_bool(val):
-    if str(val).lower().strip() in ["yes","true", "1"]:
-        return True
-    if str(val).lower().strip() in ["no","false", "0"]:
-        return False
-    try:
-        val = int(val)
-        return val != 0
-    except:
-        pass
-    return False
-
 #=================================================================
 # get_dependencies : extract products dependencies
 #=================================================================
 def get_dependencies(prods):
+    """
+    Gets full list of pre-requisite products.
+    """
     list = []
     for product in prods:
         deps = product.dependencies.split(",")
@@ -297,8 +767,13 @@ def get_dependencies(prods):
 #              is denied
 #==============================================================
 def create_dir(directory, access = 0777):
-    import string, os
-    dirs = string.split(directory, "/")
+    """
+    Creates a directory with (optional) permissions,
+    returns the part of path that existed before
+    directory creation; exits with error if access
+    is denied.
+    """
+    dirs = directory.split("/")
     existing = "";
     dir = ""
     root = ""
@@ -322,6 +797,9 @@ def create_dir(directory, access = 0777):
 #                  it is substituted by the empty string
 #==============================================================
 def substituteVars(str):
+    """
+    Performes environment variables substistution.
+    """
     str = os.path.expanduser(str)
     str = os.path.expandvars(str)
     return str
@@ -331,6 +809,10 @@ def substituteVars(str):
 #                    (and performs 'cd' command there) 
 #================================================================
 def get_program_path():
+    """
+    Returns the program directory path
+    (and make this directory current).
+    """
     path = os.path.dirname(sys.argv[0])
     if path:
         os.chdir(path)
@@ -340,14 +822,17 @@ def get_program_path():
 # check_dir : checks directory existence
 #================================================================
 def check_dir(dir):
+    """
+    Checks directory existence.
+    """
     if (os.path.islink(dir)):
         realpath = os.path.realpath(dir)
         if not os.path.exists(realpath):
-            msg = "Invalid link %s.\nThe directory %s a link points to does not exist."%(dir,realpath)
+            msg = "Invalid link %s.\nThe directory %s a link points to does not exist. Stopped..."%(dir,realpath)
             error_exit(msg, False)
     else:
         if not os.path.exists(dir):
-            msg = "Directory %s does not exist."%dir
+            msg = "Directory %s does not exist. Stopped..."%dir
             error_exit(msg, False)
     pass
 
@@ -355,28 +840,42 @@ def check_dir(dir):
 # check_disk_space : checks the disk space;
 #                    quits if there is no enough disk space
 #===============================================================
-def check_disk_space(products, scripts_dir, target_dir, tmp_dir):
+def check_disk_space(products, scripts_dir, target_dir, tmp_dir, is_force_src=False):
+    """
+    Checks if there is enough disk space to install products.
+    Quits with error if there is no enough disk space.
+    """
     install_space = 0
     temporary_space = 0
     for product in products:
         if product.install in [__TAG__NATIVE__, __TAG__PREINSTALL__]:
             continue
-        spaces = string.split(product.installdiskspace, ',')
-        prod_space = spaces[0]
-        if (len(spaces) > 1 ) and (product.install == __TAG__SOURCES__):
-            prod_space = spaces[1]
-        install_space = install_space + string.atoi(prod_space)
+        prod_space = 0
+        try:
+            spaces = product.installdiskspace.split(',')
+            prod_space = int( spaces[0] )
+            if len( spaces ) > 1 and product.install == __TAG__SOURCES__ and not is_force_src:
+                prod_space = int( spaces[1] )
+        except:
+            pass
+        install_space = install_space + prod_space
         if product.install == __TAG__SOURCES__:
-            temporary_space = max(temporary_space, string.atoi(product.temporarydiskspace))
+            tmp_space = 0
+            try:
+                tmp_space = int( product.temporarydiskspace )
+            except:
+                pass
+            temporary_space = max( temporary_space, tmp_space )
+        pass
 
     res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space))
     if res:
-        msg = "There is no enough space to install the products."
+        msg = "There is no enough space to install the products. Stopped..."
         error_exit(msg, False)
     
     res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", tmp_dir, temporary_space))
     if res:
-        msg = "There is no enough space for temporary directory."
+        msg = "There is no enough space for temporary directory. Stopped..."
         error_exit(msg, False)
     pass
  
@@ -384,6 +883,9 @@ def check_disk_space(products, scripts_dir, target_dir, tmp_dir):
 # remove_dir : removes temporary directory
 #===============================================================
 def remove_dir(path):
+    """
+    Removes temporary directory.
+    """
     if path and os.path.exists(path):
         os.system("rm -rf " + path)
     pass
@@ -393,6 +895,9 @@ def remove_dir(path):
 #                binaries
 #===============================================================
 def has_binaries(products):
+    """
+    Returns True if some product is installed in 'binaries' mode.
+    """
     for product in products:
         if product.install == __TAG__BINARIES__:
             return True
@@ -403,57 +908,120 @@ def has_binaries(products):
 #               sources
 #===============================================================
 def has_sources(products):
+    """
+    Returns True if some product is installed in 'sources' mode.
+    """
     for product in products:
         if product.install == __TAG__SOURCES__:
             return True
     return False
 
-#================================================================
-# main
-#================================================================
-    
-if __name__ == "__main__":
-    # get program dir
-    cur_dir = get_program_path()
-    # parse command line
-    [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters()
+#==============================================================
+# get_tmp_dir : gets temporary directory name
+#===============================================================
+def get_tmp_dir(dir):
+    """
+    Gets temporary directory path.
+    """
+    max_attempts = 100
+    dir_prefix="INSTALLWORK"
+    range_bottom = 0; range_top = 999999
+    for i in xrange(max_attempts):
+        tmp_dir = "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
+        if not os.path.exists( tmp_dir ):
+            return tmp_dir
+    return "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
 
-    # define xml file to be used
-    if (xml_file is None):
-        plt_name = ""
-        plt_ver  = ""
-        xml_file_name = "config.xml"
-        if os.path.exists("/etc/redhat-release"):
-            # - Red Hat Linux 8.0
-            # - Red Hat Linux 9
-            # - Mandrake Linux 10.1
-            # - Scientific Linux 3.0.5
-            data = open("/etc/redhat-release").readline()
-           res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
-           if res:
-                plt_name = "".join(res.group(1).split())
-                plt_ver  = res.group(2)
-        elif os.path.exists("/etc/debian_version"):
-            # - Debian 3.1
-            plt_name = "Debian"
-            plt_ver = open("/etc/debian_version").readline().strip()
-        _xml_file_name = "config_%s_%s.xml"%(plt_name, plt_ver)
-        if plt_name and plt_ver and os.path.exists("%s/%s"%(cur_dir, _xml_file_name)):
-            xml_file_name = _xml_file_name
-        else:
-            msg  = "Not supported Linux platform!\n"
-            msg += "Trying to use default configuration file!"
-            warning(msg)
+#==============================================================
+# get_current_platform : gets name, version and bit of 
+#                        the current user's Linux platform
+#===============================================================
+def get_current_platform():
+    """
+    Gets name, version and bit of
+    the current user's Linux platform.
+    """
+    plt_name = ""; plt_ver  = ""; plt_bit  = ""
+    if os.path.exists("/etc/issue"):
+        data = open("/etc/issue").readline()
+        res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
+        if not res:
+            # Debian identification
+            res = re.search(r'(.*)GNU/Linux\s+([\d.]*)', data)
+        if res:
+            plt_name = "".join(res.group(1).split())
+            plt_ver  = res.group(2)
+            if re.search(r'x86_64', data):
+                plt_bit  = "_64"
+                pass
+            pass
+        pass
 
-        xml_file = "%s/%s"%(cur_dir, xml_file_name)
+    return plt_name, plt_ver, plt_bit
 
-    if not xml_file or not os.path.exists(xml_file):
+#==============================================================
+# check_xml_file : checks XML file existence and readability
+#===============================================================
+def check_xml_file(xml_file):
+    """
+    Checks XML file existence and readability.
+    """
+    if not os.path.isfile(xml_file):
         msg = "Configuration file %s is not found!"%xml_file
-        error_exit(msg)
+        error_exit(msg, False)
 
     if not os.access(xml_file, os.R_OK):
         msg = "There is no read access for %s file!"%xml_file
-        error_exit(msg)
+        error_exit(msg, False)
+    pass
+
+#==============================================================
+# get_supported_plts : gets map of supported Linux platforms and
+#                      corresponding configuration files
+#===============================================================
+def get_supported_platforms(xml_file=None):
+    """
+    Gets map of supported Linux platforms and
+    corresponding configuration files.
+    """
+    platforms_map = {}
+    xml_file_list = list()
+    if xml_file:
+        xml_file_list = [ xml_file ]
+    else:
+        entry_list = os.listdir(get_program_path())
+        for entry in entry_list:
+            if re.search(r'(.*).xml', entry):
+                xml_file_list.append(os.path.abspath(entry))
+    for an_xml_file in xml_file_list: # XML files parsing
+        check_xml_file(an_xml_file)
+        filehandle = open(an_xml_file)
+        data = filehandle.read()
+        filehandle.close()
+        parser = ConfigParser()
+        parser.feed(data)
+        parser.close()
+        if parser.config.platforms is not None:
+            for plt in parser.config.platforms.split(","):
+                if not plt or plt in platforms_map.keys(): continue
+##                 print "plt = %s, xml = %s"%(strip(plt), an_xml_file)
+                platforms_map[strip(plt)] = an_xml_file
+    return platforms_map
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                    EXECUTION STARTS HERE                         #
+#                                                                  #
+#------------------------------------------------------------------#
+
+if __name__ == "__main__":
+    # parse command line
+    [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters()
+    if xml_file:   xml_file   = os.path.abspath(xml_file)
+    if target_dir: target_dir = os.path.abspath(target_dir)
+    if tmp_dir:    tmp_dir    = os.path.abspath(tmp_dir)
+    # get program dir
+    cur_dir = get_program_path()
 
     #---- GUI ----------------
 
@@ -467,17 +1035,49 @@ if __name__ == "__main__":
         env["LD_LIBRARY_PATH"] =  ".:" + env["LD_LIBRARY_PATH"]
         env["PATH"] = ".:" + env["PATH"]
 
-        cmd = "./bin/SALOME_InstallWizard %s &"%xml_file
+        cmd = "./bin/SALOME_InstallWizard"
+        if xml_file is not None:
+            cmd += " --file %s"%xml_file
+        if target_dir is not None:
+            cmd += " --target %s"%target_dir
+        if tmp_dir is not None:
+            cmd += " --tmp %s"%tmp_dir
+        cmd += "&"
         sys.exit(os.system(cmd))
 
     #-----  TUI ---------------------
 
+    msg = "Sorry, batch mode is unavailable in current version of SALOME Install Wizard!\n"
+    msg += "Use GUI mode to install SALOME, please."
+    error_exit(msg)
+    
+    # get program dir
+    cur_dir = get_program_path()
+
+    # get current Linux platform
+    plt_name = ""; plt_ver  = ""; plt_bit  = ""
+    plt_name, plt_ver, plt_bit = get_current_platform()
+    full_plt_name = plt_name + plt_ver + plt_bit
+    print "full_plt_name = %s" % full_plt_name
+    
+    # get supported Linux platforms
+    supported_plts_map = get_supported_platforms(xml_file)
+    # check: whether the current platform is supported
+    if supported_plts_map.has_key(full_plt_name):
+        # define xml file to be used
+        xml_file = supported_plts_map.get(full_plt_name, "")
+        print "set xml_file = %s" % os.path.basename(xml_file)
+        pass
+    else:
+        msg  = "Not supported Linux platform!\n"
+        warning(msg)
+
     # parse XML file -----------
     message("Parsing XML configuration file: %s"%xml_file)
     filehandle = open(xml_file)
     data = filehandle.read()
     filehandle.close()
-    parser = ConfigParser()
+    parser = ConfigParser(is_force_src)
     parser.feed(data)
     parser.close()
 
@@ -485,7 +1085,8 @@ if __name__ == "__main__":
     what_to_do = { __TAG__SOURCES__    : "install_source",
                    __TAG__BINARIES__   : "install_binary",
                    __TAG__NATIVE__     : "try_native",
-                   __TAG__PREINSTALL__ : "try_preinstalled"}
+                   __TAG__PREINSTALL__ : "try_preinstalled",
+                   __TAG__BUILDSRC__   : "install_source_and_build"}
     # source directory map
     bin_dir = ""
     if parser.config.os:
@@ -533,8 +1134,7 @@ if __name__ == "__main__":
     if not tmp_dir:
         tmp_dir = "/tmp"
     tmp_dir = substituteVars(tmp_dir)
-    import random
-    tmp_dir = "%s/INSTALLWORK%d"%(tmp_dir, random.randint(10000,100000))
+    tmp_dir = get_tmp_dir(tmp_dir)
 
     message("Creating temporary directory: " + tmp_dir)
     root_path = create_dir(tmp_dir, 0755)
@@ -545,25 +1145,25 @@ if __name__ == "__main__":
     if not os.access(tmp_dir, os.W_OK) :
         error_exit("There is no write permissions for the directory: " + tmp_dir)
         
-    # check available disk space
+    # check available disk space -----------
     message("Checking available disk space")
-    check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir)
+    check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir, is_force_src)
 
-    # change current directory
+    # change current directory -----------
     os.chdir(scripts_dir)
 
-    # get dependencies list
+    # get dependencies list -----------
     list_of_dep = get_dependencies(parser.products)
 
-    # starting
+    # starting -----------
     message("Starting ...")
     
-    # install products
+    # install products -----------
     for product in parser.products:
         message("... processing %s ..."%product.name)
         cmd = '%s/%s %s %s %s/%s %s "%s" %s'%(scripts_dir,
                                               product.script,
-                                              what_to_do[product.install],
+                                              what_to_do[product.whattodo],
                                               tmp_dir,
                                               source_dir,
                                               subdir[product.install],
@@ -572,7 +1172,7 @@ if __name__ == "__main__":
                                               product.name)
         res = os.system(cmd)
 
-    # pickup environment
+    # pickup environment -----------
     message("Creating environment files")
     for product in parser.products :
         if check_bool(product.pickupEnv):
@@ -586,9 +1186,10 @@ if __name__ == "__main__":
                                                           product.name)
             res = os.system(cmd)
 
-    # clean temporary directory
+    # clean temporary directory -----------
     message("Cleaning temporary directory")
     clean_all()
-    # finishing
+    
+    # finishing -----------
     message("Finished!")
     pass