4 Installation Wizard launching script.
9 # --- avoid "deprecation" warnings --- #
11 warnings.filterwarnings("ignore", "", DeprecationWarning)
15 import sys, os, string, re
19 # --- global variables --- #
23 # --- XML tags definition --- #
24 __TAG__SOURCES__ = "install sources"
25 __TAG__BINARIES__ = "install binaries"
26 __TAG__NATIVE__ = "use native"
27 __TAG__PREINSTALL__ = "not install"
29 #------------------------------------------------------------------#
31 # COMMAND LINE ARGUMENTS PARSER #
33 #------------------------------------------------------------------#
35 #===================================================================
36 # class OptBaseError : base parse error
37 #===================================================================
38 class OptBaseError(Exception):
40 Base option parsing exception class
42 def __init__(self, msg):
47 #===================================================================
48 # class OptError : bad option error
49 #===================================================================
50 class OptError(OptBaseError):
52 Bad option exception class
54 def __init__ (self, msg, option):
60 if self.option.short_opt and self.option.long_opt:
61 opt_prs = "%s/%s"%(self.option.short_opt,self.option.long_opt)
62 elif self.option.short_opt:
63 opt_prs = "%s"%(self.option.short_opt)
64 elif self.option.long_opt:
65 opt_prs = "%s"%(self.option.long_opt)
66 return "option %s: %s"%(opt_prs, self.msg)
69 #===================================================================
70 # class ArgError : bad option argument error
71 #===================================================================
72 class ArgError(OptBaseError):
74 Bad argument exception class
78 #===================================================================
79 # class ValError : bad command line parameter error
80 #===================================================================
81 class ValError(OptBaseError):
83 Bad parameter exception class
87 #===================================================================
88 # class ArgOption : command line option
89 #===================================================================
94 attrs = ["short_opt", "long_opt", "dest", "action", "type", "default", "metavar", "help"]
95 actions = ["store", "store_true", "store_false"]
96 types = ["string", "int", "float", "bool"]
97 def __init__(self, *args, **kwargs):
99 for attr in self.attrs: setattr(self, attr, None)
101 for i in range(len(args)):
102 if i > len(self.attrs)-1:
103 msg = "Wrong number of parameters is given (maximum is %d)" % len(self.attrs)
104 raise OptBaseError(msg)
105 setattr(self, self.attrs[i], args[i])
107 if arg not in self.attrs:
108 msg = "Invalid argument: %s" % arg
109 raise OptBaseError(msg)
110 setattr(self, arg, kwargs[arg])
111 # check short option key
112 if self.short_opt and \
113 not re.match("^-[a-zA-Z]$",self.short_opt):
114 msg = "invalid short option key; "
115 msg += "should be of the form -x (x is letter)"
116 raise OptError(msg, self)
117 # check long option key
118 if self.long_opt and \
119 not re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$",self.long_opt):
120 msg = "invalid long option key; "
121 msg += "should be of the form --word[[-word]...] "
122 msg += "(word is letters and digits sequence)"
123 raise OptError(msg, self)
124 # check that at least one option key is defined
125 if not self.short_opt and not self.long_opt:
126 msg = "invalid option; neither short nor long option key is defined"
127 raise OptError(msg, self)
129 if not self.dest and self.long_opt:
130 self.dest = self.long_opt[2:].replace('-','_')
131 if not self.dest and self.short_opt:
132 self.dest = self.short_opt[1:]
135 self.action = "store"
136 if self.action not in self.actions:
137 msg = "invalid action: %s" % self.action
138 raise OptError(msg, self)
141 if self.action in ["store_true","store_false"]: self.type = "bool"
142 else: self.type = "string"
143 if self.type not in self.types:
144 msg = "invalid type: %s" % self.type
145 raise OptError(msg, self)
146 if self.action in ["store_true","store_false"] and self.type != "bool":
147 msg = "invalid type: %s : should be 'bool' or None" % self.type
148 raise OptError(msg, self)
152 if self.type == "string": self.default = str(self.default)
153 if self.type == "int": self.default = int(self.default)
154 if self.type == "float": self.default = float(self.default)
155 if self.type == "bool": self.default = boolean(self.default)
157 msg = "invalid default value type: should be %s" % self.type
158 raise OptError(msg, self)
162 self.metavar = self.dest.upper()
170 Returns string representation of the option
174 if opt and self.action == "store" and self.metavar: opt += " %s" % self.metavar
175 if opt: opts.append(opt)
177 if opt and self.action == "store" and self.metavar: opt += "=%s" % self.metavar
178 if opt: opts.append(opt)
179 return (", ").join(opts)
181 #===================================================================
182 # class Values : resulting option values
183 #===================================================================
191 #===================================================================
192 # class ArgParser : command line arguments parser
193 #===================================================================
196 Arguments parser class
202 def add_option(self, *args, **kwargs):
203 """Register an option"""
204 o = ArgOption(*args, **kwargs)
205 self._check_option(o)
206 self.options.append(o)
209 def parse_args(self, args = None):
210 """Parse an arguments"""
211 if not args: args = sys.argv[1:]
213 for o in self.options:
215 setattr(values, o.dest, o.default)
216 elif not hasattr(values,o.dest):
217 setattr(values, o.dest, None)
219 (values, args) = self._process_args(values, args)
220 except (ArgError, ValError), e:
223 return (values, args)
225 def print_usage(self):
227 print "usage: %s [options]" % os.path.basename(sys.argv[0])
230 def print_help(self):
235 _maxwidth, _indent = 79, 2
236 if len(self.options):
237 for option in self.options:
238 if olen < len(option.to_string()): olen = len(option.to_string())
240 for option in self.options:
242 for hs in option.help.split("\n"):
245 if len("%s %s" % (s,w)) > _maxwidth:
246 strings.append(s.strip()); s = ""
248 if s.strip(): strings.append(s.strip())
249 if not strings: strings[:0] = [""]
250 print "%s%s%s" % (option.to_string(), " "*(_indent+olen-len(option.to_string())), strings[0])
251 for i in range(1, len(strings)):
252 print "%s%s" % (" "*(olen+_indent), strings[i])
255 def _check_option(self, option):
256 o = self._get_option(option.short_opt)
257 if not o: o = self._get_option(option.long_opt)
259 msg = "option conflicts with previously defined option(s)"
260 raise OptError(msg, option)
263 def _get_option(self, opt_key):
265 for o in self.options:
266 if opt_key in [o.short_opt, o.long_opt]: return o
269 def _error(self, msg):
271 sys.exit("\n%s: error: %s\n" % (os.path.basename(sys.argv[0]), msg))
274 def _check_value(self, option, value):
275 o = self._get_option(option)
277 if o.type == "string": return str(value)
278 if o.type == "int": return int(value)
279 if o.type == "float": return float(value)
280 if o.type == "bool": return boolean(value)
282 msg = "invalid value type for option %s: %s; " % (option, value)
283 msg += "should be %s" % o.type
285 raise OptBaseError("unknown error")
287 def _process_args(self, values, args):
291 for index in range(len(args)):
293 if cur_opt and cur_opt[1].action == "store":
294 setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a))
298 rargs = args[index+1:]
300 elif re.match("^-[a-zA-Z].*", a):
301 for i in range(1,len(a)):
302 if cur_opt and cur_opt[1].action == "store":
303 setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a[i:]))
306 o = self._get_option("-%s"%a[i])
308 raise ArgError("no such option: -%s"%a[i])
309 if o.action == "store_true":
310 setattr(values, o.dest, True)
311 elif o.action == "store_false":
312 setattr(values, o.dest, False)
314 cur_opt = ("-%s"%a[i], o)
316 elif re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*", a):
317 oname = ("%s="%a).split("=")[0]
318 ovalue = ("%s="%a).split("=")[1]
319 o = self._get_option(oname)
321 raise ArgError("no such option: %s" % oname)
322 if o.action == "store_true":
324 raise ValError("option %s does not take a value" % oname)
325 setattr(values, o.dest, True)
326 elif o.action == "store_false":
328 raise ValError("option %s does not take a value" % oname)
329 setattr(values, o.dest, False)
332 setattr(values, o.dest, self._check_value(oname, ovalue))
336 elif a.startswith("-"):
337 raise ArgError("bad formatted option: %s" % a)
341 if cur_opt and cur_opt[1].action == "store":
342 raise ValError("option %s requires value" % cur_opt[0])
343 return (values, rargs)
345 #------------------------------------------------------------------#
347 # XML CONFIGURATION FILES PARSER #
349 #------------------------------------------------------------------#
351 #===================================================================
352 # class Config : general configuration options : version, OS, etc...
353 #===================================================================
356 General configuration file options:
357 - Install Wizard window caption
358 - SALOME platform version
359 - Copyright and libcense info
360 - Target Linux OS version
368 self.version = strip(theVersion)
369 self.caption = strip(theCaption)
370 self.copyright = strip(theCopyright)
371 self.license = strip(theLicense)
372 self.os = strip(theOS)
374 #===================================================================
375 # class Path : default target, temporary directories options
376 #===================================================================
380 - default target directory
381 - default temporary directory
386 self.targetdir = strip(theTargetdir)
387 self.tmpdir = strip(theTmpdir)
389 #==============================================================
390 # class Product : pre-requisite product options
391 #==============================================================
396 - supported installation modes and the default one
398 - required disk space
399 - installation script
406 theSupportred = None,
407 theDependencies = None,
408 theInstalldiskspace = None,
409 theTemporarydiskspace = None,
411 thePickUpEnvironment = None):
412 self.name = strip(theName)
413 self.version = strip(theVersion)
414 self.install = strip(theInstall)
415 self.supported = strip(theSupportred)
416 self.dependencies = strip(theDependencies)
417 self.installdiskspace = strip(theInstalldiskspace)
418 self.temporarydiskspace = strip(theTemporarydiskspace)
419 self.script = strip(theScript)
420 self.pickupEnv = strip(thePickUpEnvironment)
422 #===================================================================
423 # class ConfigParser : XML files parser implementation
424 #===================================================================
425 class ConfigParser(xmllib.XMLParser):
427 XML configuration files parser
430 xmllib.XMLParser.__init__(self)
432 self.currentdata = []
436 def handle_data(self, data):
437 self.currentdata.append(data)
439 def start_product(self, attrs):
440 if not attrs.get('name', '').strip(): return
441 if check_bool(attrs.get('disable', 'false')): return
442 aProduct = Product(attrs.get('name'),
443 attrs.get('version', None),
444 attrs.get('install', None),
445 attrs.get('supported', None),
446 attrs.get('dependancies', None),
447 attrs.get('installdiskspace', None),
448 attrs.get('temporarydiskspace', None),
449 attrs.get('script', None),
450 attrs.get('pickupenv', None))
451 self.products.append(aProduct)
454 def end_product(self):
457 def start_config(self, attrs):
458 self.config = Config(attrs.get('version', None),
459 attrs.get('caption', None),
460 attrs.get('copyright', None),
461 attrs.get('license', None),
462 attrs.get('os', None))
465 def end_config(self):
468 def start_path (self, attrs):
469 self.path = Path(attrs.get('targetdir', None),
470 attrs.get('tempdir', None))
476 def getProduct(self, prod):
477 for product in self.products:
478 if product.name == prod:
482 #------------------------------------------------------------------#
484 # SERVICE FUNCTIONS #
486 #------------------------------------------------------------------#
488 #==============================================================
489 # message: prints diagnostic information
490 #==============================================================
493 Prints diagnostic information.
499 #==============================================================
500 # warning: prints warning
501 #==============================================================
512 #==============================================================
513 # error_exit : prints (optionally) error string, then prints
514 # help information and quits
515 #==============================================================
516 def error_exit(msg = "", print_help = True):
518 Prints (optionally) error string,
519 then prints help information and quits.
521 # print error message
526 # print help information
530 opt_parser.print_help()
538 #==============================================================
539 # boolean : Converts string to boolean value.
540 #==============================================================
543 Converts string to boolean value if possible.
544 Raises exception if wrong string is used.
546 if isinstance(val, types.StringType):
547 if val.strip().lower() in ["true", "yes", "ok"] : return True
548 elif val.strip().lower() in ["false", "no", "cancel"] : return False
549 else: raise TypeError("invalid boolean value")
552 #=================================================================
553 # check_bool : checks boolean value: yes/no, true/false, 1/0
554 #=================================================================
557 Checks boolean value.
565 #==============================================================
566 # clean_all : performs system cleaning before exiting
567 #==============================================================
570 Performs system cleaning before exiting.
573 remove_dir(root_path)
576 #==============================================================
577 # parse_parameters : parses command line arguments
578 #==============================================================
579 def parse_parameters():
581 Parses command line arguments.
584 opt_parser = ArgParser()
586 help_str = "Runs the Installation Wizard in the GUI mode [default].\n"
587 opt_parser.add_option("-g",
593 help_str = "Runs the Installation Wizard in the TUI mode."
594 opt_parser.add_option("-b",
596 action="store_false",
599 help_str = "The configuration xml file.\n"
600 help_str += "If this parameter is missing, then the program tries to define the "
601 help_str += "Linux platform and use the corresponding xml file. For example, "
602 help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case. "
603 help_str += "If program fails to define target Linux platform or the corresponding "
604 help_str += "xml file is not provided with the Installation Wizard, then default "
605 help_str += "config.xml file is used."
606 opt_parser.add_option("-f",
612 help_str = "The target directory the products to be installed to.\n"
613 help_str += "When used this parameter overrides the default target directory "
614 help_str += "defined in the configuration xml file."
615 opt_parser.add_option("-d",
621 help_str = "The directory to be used for temporary files.\n"
622 help_str += "When used this parameter overrides the default temporary directory "
623 help_str += "defined in the configuration xml file."
624 opt_parser.add_option("-t",
630 help_str = "Prints version information and quits."
631 opt_parser.add_option("-v",
635 help_str = "Prints this help and quits."
636 opt_parser.add_option("-h",
640 (options, args) = opt_parser.parse_args()
642 # print help info and quit
643 print "\nSALOME Installation Wizard\n"
644 opt_parser.print_help()
648 # print version info and quit
650 cmd = "./bin/SALOME_InstallWizard --version"
654 return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui]
656 #=================================================================
657 # strip : removes spaces at the beginning and at the end of the
658 # <param> if it is of string type
659 #=================================================================
662 Removes spaces at the beginning and at the end
663 of the given parameter.
665 if type(param) == types.StringType:
669 #=================================================================
670 # get_dependencies : extract products dependencies
671 #=================================================================
672 def get_dependencies(prods):
674 Gets full list of pre-requisite products.
677 for product in prods:
678 deps = product.dependencies.split(",")
680 if dep and not dep in list:
683 if product and not product in list:
684 list.append( product.name )
686 return " ".join( list )
688 #==============================================================
689 # create_dir : creates a directory with (optional) permissions,
690 # returns the part of path that existed before
691 # directory creation; exits with error if access
693 #==============================================================
694 def create_dir(directory, access = 0777):
696 Creates a directory with (optional) permissions,
697 returns the part of path that existed before
698 directory creation; exits with error if access
701 dirs = string.split(directory, "/")
706 if len(subdir) == 0: continue
707 dir = "%s/%s"%(dir, subdir)
708 if os.path.exists(dir):
712 os.mkdir(dir, access)
714 error_exit("Can't create directory: %s.\nAccess is denied."%directory)
715 if dir == "%s/%s"%(existing, subdir):
719 #==============================================================
720 # substituteVars : performes environment variables substistution
721 # the given string; if varibale is not defined
722 # it is substituted by the empty string
723 #==============================================================
724 def substituteVars(str):
726 Performes environment variables substistution.
728 str = os.path.expanduser(str)
729 str = os.path.expandvars(str)
732 #================================================================
733 # get_program_path : gets program's directory path
734 # (and performs 'cd' command there)
735 #================================================================
736 def get_program_path():
738 Returns the program directory path
739 (and make this directory current).
741 path = os.path.dirname(sys.argv[0])
746 #================================================================
747 # check_dir : checks directory existence
748 #================================================================
751 Checks directory existence.
753 if (os.path.islink(dir)):
754 realpath = os.path.realpath(dir)
755 if not os.path.exists(realpath):
756 msg = "Invalid link %s.\nThe directory %s a link points to does not exist. Stopped..."%(dir,realpath)
757 error_exit(msg, False)
759 if not os.path.exists(dir):
760 msg = "Directory %s does not exist. Stopped..."%dir
761 error_exit(msg, False)
764 #===============================================================
765 # check_disk_space : checks the disk space;
766 # quits if there is no enough disk space
767 #===============================================================
768 def check_disk_space(products, scripts_dir, target_dir, tmp_dir):
770 Checks if there is enough disk space to install products.
771 Quits with error if there is no enough disk space.
775 for product in products:
776 if product.install in [__TAG__NATIVE__, __TAG__PREINSTALL__]:
778 spaces = string.split(product.installdiskspace, ',')
779 prod_space = spaces[0]
780 if (len(spaces) > 1 ) and (product.install == __TAG__SOURCES__):
781 prod_space = spaces[1]
782 install_space = install_space + string.atoi(prod_space)
783 if product.install == __TAG__SOURCES__:
784 temporary_space = max(temporary_space, string.atoi(product.temporarydiskspace))
786 res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space))
788 msg = "There is no enough space to install the products. Stopped..."
789 error_exit(msg, False)
791 res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", tmp_dir, temporary_space))
793 msg = "There is no enough space for temporary directory. Stopped..."
794 error_exit(msg, False)
797 #===============================================================
798 # remove_dir : removes temporary directory
799 #===============================================================
800 def remove_dir(path):
802 Removes temporary directory.
804 if path and os.path.exists(path):
805 os.system("rm -rf " + path)
808 #==============================================================
809 # has_binaries : returns True if some product is installed from
811 #===============================================================
812 def has_binaries(products):
814 Returns True if some product is installed in 'binaries' mode.
816 for product in products:
817 if product.install == __TAG__BINARIES__:
821 #==============================================================
822 # has_sources : returns True if some product is installed from
824 #===============================================================
825 def has_sources(products):
827 Returns True if some product is installed in 'sources' mode.
829 for product in products:
830 if product.install == __TAG__SOURCES__:
834 #==============================================================
835 # get_tmp_dir : gets temporary directory name
836 #===============================================================
837 def get_tmp_dir(dir):
839 Gets temporary directory path.
842 dir_prefix="INSTALLWORK"
843 range_bottom = 0; range_top = 999999
844 for i in xrange(max_attempts):
845 tmp_dir = "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
846 if not os.path.exists( tmp_dir ):
848 return "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
850 #------------------------------------------------------------------#
852 # EXECUTION STARTS HERE #
854 #------------------------------------------------------------------#
856 if __name__ == "__main__":
858 cur_dir = get_program_path()
860 [xml_file, target_dir, tmp_dir, is_gui] = parse_parameters()
862 # define xml file to be used
863 if (xml_file is None):
866 xml_file_name = "config.xml"
867 if os.path.exists("/etc/redhat-release"):
868 # - Red Hat Linux 8.0
870 # - Mandrake Linux 10.1
871 # - Scientific Linux 3.0.5
873 data = open("/etc/redhat-release").readline()
874 res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
876 plt_name = "".join(res.group(1).split())
877 plt_ver = res.group(2)
878 elif os.path.exists("/etc/debian_version"):
881 plt_ver = open("/etc/debian_version").readline().strip()
882 elif os.path.exists("/etc/mandriva-release"):
883 # - Mandriva 2006 (an additional check if above check fails)
884 data = open("/etc/mandriva-release").readline()
885 res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
887 plt_name = "".join(res.group(1).split())
888 plt_ver = res.group(2)
889 _xml_file_name = "config_%s_%s.xml"%(plt_name, plt_ver)
890 if plt_name and plt_ver and os.path.exists("%s/%s"%(cur_dir, _xml_file_name)):
891 xml_file_name = _xml_file_name
893 msg = "Not supported Linux platform!\n"
894 msg += "Trying to use default configuration file!"
897 xml_file = "%s/%s"%(cur_dir, xml_file_name)
899 if not xml_file or not os.path.exists(xml_file):
900 msg = "Configuration file %s is not found!"%xml_file
903 if not os.access(xml_file, os.R_OK):
904 msg = "There is no read access for %s file!"%xml_file
907 #---- GUI ----------------
911 if not env.has_key("PATH") :
913 if not env.has_key("LD_LIBRARY_PATH") :
914 env["LD_LIBRARY_PATH"] = ""
916 env["LD_LIBRARY_PATH"] = ".:" + env["LD_LIBRARY_PATH"]
917 env["PATH"] = ".:" + env["PATH"]
919 cmd = "./bin/SALOME_InstallWizard --file %s"%xml_file
920 if target_dir is not None:
921 cmd += " --target %s"%target_dir
922 if tmp_dir is not None:
923 cmd += " --tmp %s"%tmp_dir
925 sys.exit(os.system(cmd))
927 #----- TUI ---------------------
929 # parse XML file -----------
930 message("Parsing XML configuration file: %s"%xml_file)
931 filehandle = open(xml_file)
932 data = filehandle.read()
934 parser = ConfigParser()
939 what_to_do = { __TAG__SOURCES__ : "install_source",
940 __TAG__BINARIES__ : "install_binary",
941 __TAG__NATIVE__ : "try_native",
942 __TAG__PREINSTALL__ : "try_preinstalled"}
943 # source directory map
946 bin_dir += "/%s"%parser.config.os
947 subdir = { __TAG__SOURCES__ : "SOURCES",
948 __TAG__BINARIES__ : "BINARIES" + bin_dir,
949 __TAG__NATIVE__ : "",
950 __TAG__PREINSTALL__ : ""}
952 # check scripts directory -----------
953 scripts_dir = "%s/%s"%(cur_dir, "config_files")
954 check_dir(scripts_dir)
956 # check products archives directories -----------
957 has_bin = has_binaries(parser.products)
958 has_src = has_sources(parser.products)
959 source_dir = "%s/%s"%(cur_dir, "Products")
961 if has_src or has_bin:
962 check_dir(source_dir)
965 check_dir("%s/%s"%(source_dir,subdir[__TAG__SOURCES__]))
968 check_dir("%s/%s"%(source_dir,subdir[__TAG__BINARIES__]))
970 # check/create target dir -----------
971 if target_dir is None:
972 target_dir = parser.path.targetdir
973 target_dir = substituteVars(target_dir)
975 message("Creating target directory: " + target_dir)
976 create_dir(target_dir, 0755)
978 if not os.path.exists(target_dir):
979 error_exit("Invalid target directory: " + target_dir)
981 if not os.access(target_dir, os.W_OK) :
982 error_exit("There is no write permissions for the directory: " + target_dir)
984 # check/create temporary dir -----------
986 tmp_dir = parser.path.tmpdir
989 tmp_dir = substituteVars(tmp_dir)
990 tmp_dir = get_tmp_dir(tmp_dir)
992 message("Creating temporary directory: " + tmp_dir)
993 root_path = create_dir(tmp_dir, 0755)
995 if not os.path.exists(tmp_dir):
996 error_exit("Invalid temporary directory: " + tmp_dir)
998 if not os.access(tmp_dir, os.W_OK) :
999 error_exit("There is no write permissions for the directory: " + tmp_dir)
1001 # check available disk space -----------
1002 message("Checking available disk space")
1003 check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir)
1005 # change current directory -----------
1006 os.chdir(scripts_dir)
1008 # get dependencies list -----------
1009 list_of_dep = get_dependencies(parser.products)
1011 # starting -----------
1012 message("Starting ...")
1014 # install products -----------
1015 for product in parser.products:
1016 message("... processing %s ..."%product.name)
1017 cmd = '%s/%s %s %s %s/%s %s "%s" %s'%(scripts_dir,
1019 what_to_do[product.install],
1022 subdir[product.install],
1026 res = os.system(cmd)
1028 # pickup environment -----------
1029 message("Creating environment files")
1030 for product in parser.products :
1031 if check_bool(product.pickupEnv):
1032 cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s'%(scripts_dir,
1036 subdir[product.install],
1040 res = os.system(cmd)
1042 # clean temporary directory -----------
1043 message("Cleaning temporary directory")
1046 # finishing -----------
1047 message("Finished!")