source: grass/trunk/lib/init/grass.py@ 59210

Last change on this file since 59210 was 59210, checked in by martinl, 10 years ago

grass.py: check if GRASS is already running

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-python
File size: 44.4 KB
Line 
1#!/usr/bin/env python
2#############################################################################
3#
4# MODULE: GRASS initialization script
5# AUTHOR(S): Original author unknown - probably CERL
6# Andreas Lange <andreas.lange rhein-main.de>
7# Huidae Cho <grass4u gmail.com>
8# Justin Hickey <jhickey hpcc.nectec.or.th>
9# Markus Neteler <neteler osgeo.org>
10# Hamish Bowman <hamish_b yahoo.com>
11#
12# GRASS 7: converted to Python (based on init.sh shell
13# script from GRASS 6) by Glynn Clements
14# Martin Landa <landa.martin gmail.com>
15# Luca Delucchi <lucadeluge gmail.com>
16# PURPOSE: Sets up environment variables, parses any remaining
17# command line options for setting the GISDBASE, LOCATION,
18# and/or MAPSET. Finally it starts GRASS with the appropriate
19# user interface and cleans up after it is finished.
20# COPYRIGHT: (C) 2000-2013 by the GRASS Development Team
21#
22# This program is free software under the GNU General
23# Public License (>=v2). Read the file COPYING that
24# comes with GRASS for details.
25#
26#############################################################################
27
28import sys
29import os
30import atexit
31import string
32import subprocess
33import re
34import platform
35import tempfile
36
37# Variables substituted during build process
38if 'GISBASE' in os.environ:
39 gisbase = os.environ['GISBASE']
40else:
41 gisbase = "@GISBASE@"
42cmd_name = "@START_UP@"
43grass_version = "@GRASS_VERSION_NUMBER@"
44ld_library_path_var = '@LD_LIBRARY_PATH_VAR@'
45if 'GRASS_PROJSHARE' in os.environ:
46 config_projshare = os.environ['GRASS_PROJSHARE']
47else:
48 config_projshare = "@CONFIG_PROJSHARE@"
49
50# configuration directory
51grass_env_file = None # see check_shell()
52if sys.platform == 'win32':
53 grass_config_dirname = "GRASS7"
54 grass_config_dir = os.path.join(os.getenv('APPDATA'), grass_config_dirname)
55else:
56 grass_config_dirname = ".grass7"
57 grass_config_dir = os.path.join(os.getenv('HOME'), grass_config_dirname)
58
59gisbase = os.path.normpath(gisbase)
60
61# i18N
62import gettext
63gettext.install('grasslibs', os.path.join(gisbase, 'locale'), unicode=True)
64
65tmpdir = None
66lockfile = None
67remove_lockfile = True
68location = None
69create_new = None
70grass_gui = None
71
72
73def warning(text):
74 sys.stderr.write(_("WARNING") + ': ' + text + os.linesep)
75
76
77def try_remove(path):
78 try:
79 os.remove(path)
80 except:
81 pass
82
83
84def try_rmdir(path):
85 try:
86 os.rmdir(path)
87 except:
88 pass
89
90
91def clean_env():
92 env_curr = read_gisrc()
93 env_new = {}
94 for k,v in env_curr.iteritems():
95 if 'MONITOR' not in k:
96 env_new[k] = v
97
98 write_gisrc(env_new)
99
100
101def cleanup_dir(path):
102 if not path:
103 return
104
105 for root, dirs, files in os.walk(path, topdown=False):
106 for name in files:
107 try_remove(os.path.join(root, name))
108 for name in dirs:
109 try_rmdir(os.path.join(root, name))
110
111
112def cleanup():
113 tmpdir, lockfile, remove_lockfile
114 # all exits after setting up tmp dirs (system/location) should
115 # also tidy it up
116 cleanup_dir(tmpdir)
117 try_rmdir(tmpdir)
118 if location:
119 tmpdir_loc = os.path.join(location, ".tmp")
120 cleanup_dir(tmpdir_loc)
121 try_rmdir(tmpdir_loc)
122
123 # remove lock-file if requested
124 if lockfile and remove_lockfile:
125 try_remove(lockfile)
126
127
128def fatal(msg):
129 sys.stderr.write(msg + os.linesep)
130 sys.exit(_("Exiting..."))
131
132
133def message(msg):
134 sys.stderr.write(msg + "\n")
135 sys.stderr.flush()
136
137
138def readfile(path):
139 f = open(path, 'r')
140 s = f.read()
141 f.close()
142 return s
143
144
145def writefile(path, s):
146 f = open(path, 'w')
147 f.write(s)
148 f.close()
149
150
151def call(cmd, **kwargs):
152 if windows:
153 kwargs['shell'] = True
154 return subprocess.call(cmd, **kwargs)
155
156
157def Popen(cmd, **kwargs):
158 if windows:
159 kwargs['shell'] = True
160 return subprocess.Popen(cmd, **kwargs)
161
162
163def gfile(*args):
164 return os.path.join(gisbase, *args)
165
166help_text = r"""GRASS GIS %s
167Geographic Resources Analysis Support System (GRASS GIS).
168
169%s:
170 $CMD_NAME [-h | -help | --help] [-v | --version] [-c | -c geofile | -c EPSG:code]
171 [-text | -gui] [--config param]
172 [[[<GISDBASE>/]<LOCATION_NAME>/]<MAPSET>]
173
174%s:
175 -h or -help or --help %s
176 -v or --version %s
177 -c %s
178 -text %s
179 %s
180 -gui %s
181 %s
182 --config %s
183 %s
184
185%s:
186 GISDBASE %s
187 LOCATION_NAME %s
188 MAPSET %s
189
190 GISDBASE/LOCATION_NAME/MAPSET %s
191
192%s:
193 GRASS_GUI %s
194 GRASS_HTML_BROWSER %s
195 GRASS_ADDON_PATH %s
196 GRASS_ADDON_BASE %s
197 GRASS_BATCH_JOB %s
198 GRASS_PYTHON %s
199""" % (grass_version,
200 _("Usage"),
201 _("Flags"),
202 _("print this help message"),
203 _("show version information and exit"),
204 _("create given database, location or mapset if it doesn't exist"),
205 _("use text based interface"),
206 _("and set as default"),
207 _("use $DEFAULT_GUI graphical user interface"),
208 _("and set as default"),
209 _("print GRASS configuration parameters"),
210 _("options: arch,build,compiler,path,revision"),
211 _("Parameters"),
212 _("initial database (path to GIS data)"),
213 _("initial location"),
214 _("initial mapset"),
215 _("fully qualified initial mapset directory"),
216 _("Environment variables relevant for startup"),
217 _("select GUI (text, gui)"),
218 _("set html web browser for help pages"),
219 _("set additional path(s) to local GRASS modules or user scripts"),
220 _("set additional GISBASE for locally installed GRASS Addons"),
221 _("shell script to be processed as batch job"),
222 _("set python shell name to override 'python'"))
223
224
225def help_message():
226 t = string.Template(help_text)
227 s = t.substitute(CMD_NAME=cmd_name, DEFAULT_GUI=default_gui)
228 sys.stderr.write(s)
229
230
231def create_tmp():
232 global tmpdir
233 ## use $TMPDIR if it exists, then $TEMP, otherwise /tmp
234 tmp = os.getenv('TMPDIR')
235 if not tmp:
236 tmp = os.getenv('TEMP')
237 if not tmp:
238 tmp = os.getenv('TMP')
239 if not tmp:
240 tmp = tempfile.gettempdir()
241 if tmp:
242 tmpdir = os.path.join(tmp, "grass7-%(user)s-%(lock)s" % {'user': user,
243 'lock': gis_lock})
244 try:
245 os.mkdir(tmpdir, 0700)
246 except:
247 tmp = None
248 if not tmp:
249 for ttmp in ("/tmp", "/var/tmp", "/usr/tmp"):
250 tmp = ttmp
251 tmpdir = os.path.join(tmp, "grass7-%(user)s-%(lock)s" % {
252 'user': user, 'lock': gis_lock})
253 try:
254 os.mkdir(tmpdir, 0700)
255 except:
256 tmp = None
257 if tmp:
258 break
259 if not tmp:
260 fatal(_("Unable to create temporary directory <grass7-%(user)s-" \
261 "%(lock)s>! Exiting.") % {'user': user, 'lock': gis_lock})
262
263
264def create_gisrc():
265 global gisrc, gisrcrc
266 # Set the session grassrc file
267 gisrc = os.path.join(tmpdir, "gisrc")
268 os.environ['GISRC'] = gisrc
269
270 # remove invalid GISRC file to avoid disturbing error messages:
271 try:
272 s = readfile(gisrcrc)
273 if "UNKNOWN" in s:
274 try_remove(gisrcrc)
275 s = None
276 except:
277 s = None
278
279 # Copy the global grassrc file to the session grassrc file
280 if s:
281 writefile(gisrc, s)
282
283
284def read_gisrc():
285 kv = {}
286 try:
287 f = open(gisrc, 'r')
288 except IOError:
289 return kv
290
291 for line in f:
292 k, v = line.split(':', 1)
293 kv[k.strip()] = v.strip()
294 f.close()
295
296 return kv
297
298
299def read_env_file(path):
300 kv = {}
301 f = open(path, 'r')
302 for line in f:
303 k, v = line.split(':', 1)
304 kv[k.strip()] = v.strip()
305 f.close()
306 return kv
307
308
309def write_gisrc(kv):
310 f = open(gisrc, 'w')
311 for k, v in kv.iteritems():
312 f.write("%s: %s\n" % (k, v))
313 f.close()
314
315
316def read_gui():
317 global grass_gui
318 # At this point the GRASS user interface variable has been set from the
319 # command line, been set from an external environment variable, or is
320 # not set. So we check if it is not set
321 if not grass_gui:
322 # Check for a reference to the GRASS user interface in the grassrc file
323 if os.access(gisrc, os.R_OK):
324 kv = read_gisrc()
325 if 'GRASS_GUI' in os.environ:
326 grass_gui = os.environ['GRASS_GUI']
327 elif 'GUI' in kv:
328 grass_gui = kv['GUI']
329 elif 'GRASS_GUI' in kv:
330 # For backward compatibility (GRASS_GUI renamed to GUI)
331 grass_gui = kv['GRASS_GUI']
332 else:
333 # Set the GRASS user interface to the default if needed
334 grass_gui = default_gui
335
336 if not grass_gui:
337 grass_gui = default_gui
338
339 if grass_gui == 'gui':
340 grass_gui = default_gui
341
342 # FIXME oldtcltk, gis.m, d.m no longer exist
343 if grass_gui in ['d.m', 'gis.m', 'oldtcltk', 'tcltk']:
344 warning(_("GUI <%s> not supported in this version") % grass_gui)
345 grass_gui = default_gui
346
347
348def path_prepend(dir, var):
349 path = os.getenv(var)
350 if path:
351 path = dir + os.pathsep + path
352 else:
353 path = dir
354 os.environ[var] = path
355
356
357def path_append(dir, var):
358 path = os.getenv(var)
359 if path:
360 path = path + os.pathsep + dir
361 else:
362 path = dir
363 os.environ[var] = path
364
365
366def set_paths():
367 # addons (path)
368 addon_path = os.getenv('GRASS_ADDON_PATH')
369 if addon_path:
370 for path in addon_path.split(os.pathsep):
371 path_prepend(addon_path, 'PATH')
372
373 # addons (base)
374 addon_base = os.getenv('GRASS_ADDON_BASE')
375 if not addon_base:
376 addon_base = os.path.join(grass_config_dir, 'addons')
377 os.environ['GRASS_ADDON_BASE'] = addon_base
378 path_prepend(os.path.join(addon_base, 'scripts'), 'PATH')
379 path_prepend(os.path.join(addon_base, 'bin'), 'PATH')
380
381 # standard installation
382 path_prepend(gfile('scripts'), 'PATH')
383 path_prepend(gfile('bin'), 'PATH')
384
385 # Set PYTHONPATH to find GRASS Python modules
386 path_prepend(gfile('etc', 'python'), 'PYTHONPATH')
387
388 # set path for the GRASS man pages
389 grass_man_path = os.path.join(gisbase, 'docs', 'man')
390 addons_man_path = os.path.join(addon_base, 'docs', 'man')
391 man_path = os.getenv('MANPATH')
392 sys_man_path = None
393 if man_path:
394 path_prepend(addons_man_path, 'MANPATH')
395 path_prepend(grass_man_path, 'MANPATH')
396 else:
397 try:
398 nul = open(os.devnull, 'w')
399 p = Popen(['manpath'], stdout=subprocess.PIPE, stderr=nul)
400 nul.close()
401 s = p.stdout.read()
402 p.wait()
403 sys_man_path = s.strip()
404 except:
405 pass
406
407 if sys_man_path:
408 os.environ['MANPATH'] = sys_man_path
409 path_prepend(addons_man_path, 'MANPATH')
410 path_prepend(grass_man_path, 'MANPATH')
411 else:
412 os.environ['MANPATH'] = addons_man_path
413 path_prepend(grass_man_path, 'MANPATH')
414
415 # Add .py (Python) to list of executable extensions to search for
416 # in MS-Windows PATH
417 if windows:
418 path_append('.PY', 'PATHEXT')
419
420
421def find_exe(pgm):
422 for dir in os.getenv('PATH').split(os.pathsep):
423 path = os.path.join(dir, pgm)
424 if os.access(path, os.X_OK):
425 return path
426 return None
427
428
429def set_defaults():
430 # GRASS_PAGER
431 if not os.getenv('GRASS_PAGER'):
432 if find_exe("more"):
433 pager = "more"
434 elif find_exe("less"):
435 pager = "less"
436 elif windows:
437 pager = "more"
438 else:
439 pager = "cat"
440 os.environ['GRASS_PAGER'] = pager
441
442 # GRASS_PYTHON
443 if not os.getenv('GRASS_PYTHON'):
444 if windows:
445 os.environ['GRASS_PYTHON'] = "python.exe"
446 else:
447 os.environ['GRASS_PYTHON'] = "python"
448
449 # GRASS_GNUPLOT
450 if not os.getenv('GRASS_GNUPLOT'):
451 os.environ['GRASS_GNUPLOT'] = "gnuplot -persist"
452
453 # GRASS_PROJSHARE
454 if not os.getenv('GRASS_PROJSHARE'):
455 os.environ['GRASS_PROJSHARE'] = config_projshare
456
457
458def set_browser():
459 # GRASS_HTML_BROWSER
460 browser = os.getenv('GRASS_HTML_BROWSER')
461 if not browser:
462 if macosx:
463 # OSX doesn't execute browsers from the shell PATH - route thru a
464 # script
465 browser = gfile('etc', "html_browser_mac.sh")
466 os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b com.apple.helpviewer"
467
468 if windows or cygwin:
469 # MinGW startup moved to into init.bat
470 browser = "explorer"
471 else:
472 # the usual suspects
473 browsers = ["xdg-open", "htmlview", "konqueror", "mozilla",
474 "mozilla-firefox", "firefox", "iceweasel", "opera",
475 "netscape", "dillo", "lynx", "links", "w3c"]
476 for b in browsers:
477 if find_exe(b):
478 browser = b
479 break
480
481 elif macosx:
482 # OSX doesn't execute browsers from the shell PATH - route thru a
483 # script
484 os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b %s" % browser
485 browser = gfile('etc', "html_browser_mac.sh")
486
487 if not browser:
488 warning(_("Searched for a web browser, but none found"))
489 # even so we set konqueror to make lib/gis/parser.c happy:
490 browser = "konqueror"
491
492 os.environ['GRASS_HTML_BROWSER'] = browser
493
494
495def grass_intro():
496 intro = _(r"""
497WELCOME TO GRASS %s
498
499 1) Have at your side all available GRASS GIS tutorials
500
501 2) When working on your location, the following materials
502 are extremely useful:
503 - A topographic map of your area
504 - Current catalog of available computer maps
505
506 3) heck the GRASS GIS web pages for supporting mailing lists and more:
507 http://grass.osgeo.org
508""") % grass_version
509 sys.stderr.write(intro)
510
511 sys.stderr.write("\n")
512 sys.stderr.write(_("Hit RETURN to continue"))
513 sys.stdin.readline()
514
515 # for convenience, define pwd as GISDBASE:
516 s = r"""GISDBASE: %s
517LOCATION_NAME: <UNKNOWN>
518MAPSET: <UNKNOWN>
519""" % os.getcwd()
520 writefile(gisrc, s)
521
522
523def check_gui():
524 global grass_gui, wxpython_base
525 # Check if we are running X windows by checking the DISPLAY variable
526 if os.getenv('DISPLAY') or windows or macosx:
527 # Check if python is working properly
528 if grass_gui == 'wxpython':
529 nul = open(os.devnull, 'w')
530 p = Popen([os.environ['GRASS_PYTHON']], stdin=subprocess.PIPE,
531 stdout=nul, stderr=nul)
532 nul.close()
533 p.stdin.write("variable=True")
534 p.stdin.close()
535 p.wait()
536 if p.returncode == 0:
537 # Set the wxpython base directory
538 wxpython_base = gfile("etc", "gui", "wxpython")
539 else:
540 # Python was not found - switch to text interface mode
541 warning(_("The python command does not work as expected!\n"
542 "Please check your GRASS_PYTHON environment variable.\n"
543 "Use the -help option for details.\n"
544 "Switching to text based interface mode.\n\n"
545 "Hit RETURN to continue.\n"))
546 sys.stdin.readline()
547 grass_gui = 'text'
548
549 else:
550 # Display a message if a graphical interface was expected
551 if grass_gui != 'text':
552 # Set the interface mode to text
553 warning(_("It appears that the X Windows system is not active.\n"
554 "A graphical based user interface is not supported.\n"
555 "Switching to text based interface mode.\n\n"
556 "Hit RETURN to continue"""))
557 sys.stdin.readline()
558 grass_gui = 'text'
559
560 # Save the user interface variable in the grassrc file - choose a temporary
561 # file name that should not match another file
562 if os.access(gisrc, os.F_OK):
563 kv = read_gisrc()
564 kv['GUI'] = grass_gui
565 write_gisrc(kv)
566
567
568def non_interactive(arg, geofile=None):
569 global gisdbase, location_name, mapset, location
570 # Try non-interactive startup
571 l = None
572
573 if arg == '-':
574 if location:
575 l = location
576 else:
577 l = arg
578
579 if l:
580 if l == '.':
581 l = os.getcwd()
582 elif not os.path.isabs(l):
583 l = os.path.abspath(l)
584
585 l, mapset = os.path.split(l)
586 if not mapset:
587 l, mapset = os.path.split(l)
588 l, location_name = os.path.split(l)
589 gisdbase = l
590
591 if gisdbase and location_name and mapset:
592 location = os.path.join(gisdbase, location_name, mapset)
593
594 # check if 'location' is a valid GRASS location/mapset
595 if not os.access(os.path.join(location, "WIND"), os.R_OK):
596 if not create_new:
597 # 'location' is not valid, check if 'location_name' is
598 # a valid GRASS location
599 if not os.path.exists(os.path.join(gisdbase, location_name)):
600 fatal(_("Location <%s> doesn't exist") % os.path.join(gisdbase, location_name))
601 elif 'PERMANENT' not in os.listdir(os.path.join(gisdbase, location_name)) or \
602 not os.path.isdir(os.path.join(gisdbase, location_name, 'PERMANENT')) or \
603 not os.path.isfile((os.path.join(gisdbase, location_name, 'PERMANENT',
604 'DEFAULT_WIND'))):
605 fatal(_("ERROR: <%s> is not a valid GRASS location") % \
606 os.path.join(gisdbase, location_name))
607 else:
608 fatal(_("Mapset <%s> doesn't exist in GRASS location <%s>. "
609 "A new mapset can be created by '-c' switch.") % (mapset, location_name))
610
611 else:
612 # 'location' is not valid, the user wants to create
613 # mapset on the fly
614 if not os.access(os.path.join(gisdbase, location_name,
615 "PERMANENT",
616 "DEFAULT_WIND"), os.F_OK):
617 # 'location_name' is not a valid GRASS location,
618 # create new location and 'PERMANENT' mapset
619 gisdbase = os.path.join(gisdbase, location_name)
620 location_name = mapset
621 mapset = "PERMANENT"
622 if os.access(os.path.join(os.path.join(gisdbase,
623 location_name,
624 "PERMANENT",
625 "DEFAULT_WIND")),
626 os.F_OK):
627 fatal(_("Failed to create new location. "
628 "The location <%s> already exists." % location_name))
629
630 if gfile('etc', 'python') not in sys.path:
631 sys.path.append(gfile('etc', 'python'))
632 from grass.script import core as grass
633
634 try:
635 if geofile and geofile.upper().find('EPSG:') > -1:
636 # create location using EPSG code
637 epsg = geofile.split(':', 1)[1]
638 grass.create_location(gisdbase, location_name,
639 epsg=epsg)
640 else:
641 # create location using georeferenced file
642 grass.create_location(gisdbase, location_name,
643 filename=geofile)
644 except grass.ScriptError, e:
645 fatal(e.value.strip('"').strip("'").replace('\\n',
646 os.linesep))
647 else:
648 # 'location_name' is a valid GRASS location,
649 # create new mapset
650 os.mkdir(location)
651 # copy PERMANENT/DEFAULT_WIND to <mapset>/WIND
652 s = readfile(os.path.join(gisdbase, location_name,
653 "PERMANENT", "DEFAULT_WIND"))
654 writefile(os.path.join(location, "WIND"), s)
655 message(_("Missing WIND file fixed"))
656
657 if os.access(gisrc, os.R_OK):
658 kv = read_gisrc()
659 else:
660 kv = {}
661
662 kv['GISDBASE'] = gisdbase
663 kv['LOCATION_NAME'] = location_name
664 kv['MAPSET'] = mapset
665 write_gisrc(kv)
666 else:
667 fatal(_("GISDBASE, LOCATION_NAME and MAPSET variables not set properly.\n"
668 "Interactive startup needed."))
669
670
671def set_data():
672 # User selects LOCATION and MAPSET if not set
673 if not location:
674 # Check for text interface
675 if grass_gui == 'text':
676 pass
677 # Check for GUI
678 elif grass_gui == 'wxpython':
679 gui_startup()
680 else:
681 # Shouldn't need this but you never know
682 fatal(_("Invalid user interface specified - <%s>.\n"
683 "Use the --help option to see valid interface names.") % grass_gui)
684
685
686def gui_startup():
687 if grass_gui == 'wxpython':
688 thetest = call([os.getenv('GRASS_PYTHON'),
689 gfile(wxpython_base, "gis_set.py")])
690
691 if thetest == 0:
692 pass
693 elif thetest == 1:
694 # The startup script printed an error message so wait
695 # for user to read it
696 message(_("Error in GUI startup. If necessary, please "
697 "report this error to the GRASS developers.\n"
698 "Switching to text mode now.\n\n"
699 "Hit RETURN to continue..."))
700 sys.stdin.readline()
701
702 os.execlp(cmd_name, "-text")
703 sys.exit(1)
704 elif thetest == 2:
705 # User wants to exit from GRASS
706 message(_("Received EXIT message from GUI.\nGRASS is not started. Bye."))
707 sys.exit(0)
708 else:
709 fatal(_("Invalid return code from GUI startup script.\n"
710 "Please advise GRASS developers of this error."))
711
712
713def load_gisrc():
714 global gisdbase, location_name, mapset, location
715 kv = read_gisrc()
716 gisdbase = kv.get('GISDBASE')
717 location_name = kv.get('LOCATION_NAME')
718 mapset = kv.get('MAPSET')
719 if not gisdbase or not location_name or not mapset:
720 fatal(_("Error reading data path information from g.gisenv.\n"
721 "GISDBASE=%(gisbase)s\n"
722 "LOCATION_NAME=%(location)s\n"
723 "MAPSET=%(mapset)s\n\n"
724 "Check the <%s(file)> file." % \
725 {'gisbase': gisdbase, 'location': location_name,
726 'mapset': mapset, 'file': gisrcrc}))
727
728 location = os.path.join(gisdbase, location_name, mapset)
729
730
731# load environmental variables from grass_env_file
732def load_env():
733 if not os.access(grass_env_file, os.R_OK):
734 return
735
736 for line in readfile(grass_env_file).split(os.linesep):
737 try:
738 k, v = map(lambda x: x.strip(), line.strip().split(' ', 1)[1].split('=', 1))
739 except:
740 continue
741 os.environ[k] = v
742 # Allow for mixed ISIS-GRASS Environment
743 if os.getenv('ISISROOT'):
744 isis = os.getenv('ISISROOT')
745 os.environ['ISIS_LIB'] = isis + os.sep + "lib"
746 os.environ['ISIS_3RDPARTY'] = isis + os.sep + "3rdParty" + os.sep + "lib"
747 os.environ['QT_PLUGIN_PATH'] = isis + os.sep + "3rdParty" + os.sep + "plugins"
748 #os.environ['ISIS3DATA'] = isis + "$ISIS3DATA"
749 libpath = os.getenv('LD_LIBRARY_PATH', '')
750 isislibpath = os.getenv('ISIS_LIB')
751 isis3rdparty = os.getenv('ISIS_3RDPARTY')
752 os.environ['LD_LIBRARY_PATH'] = libpath + os.pathsep + isislibpath + os.pathsep + isis3rdparty
753
754
755def set_language():
756 # This function is used to override system default language and locale
757 # Such override can be requested only from wxGUI
758 # An override if user has provided correct environmental variables as
759 # LC_MESSAGES or LANG is not necessary.
760 # Unfortunately currently a working solution for Windows is lacking
761 # thus it always on Vista and XP will print an error.
762 # See discussion for Windows not following its own documentation and
763 # not accepting ISO codes as valid locale identifiers http://bugs.python.org/issue10466
764 import locale
765
766 # Override value is stored in wxGUI preferences file.
767 # As it's the only thing required, we'll just grep it out.
768 try:
769 fd = open(os.path.join(grass_config_dir, 'wx'), 'r')
770 except:
771 # Language override has not been defined or is inaccessible
772 return
773 language = 'None' # Such string sometimes is present in wx file
774 for line in fd:
775 if re.search('^language', line):
776 line = line.rstrip('%s' % os.linesep)
777 language = ''.join(line.split(';')[-1:])
778 break
779 if language == 'None':
780 # Language override is disabled (system language specified)
781 return
782
783 warning("A language override has been requested. Trying to switch GRASS into '%s'..." % language)
784
785 # Even if setting locale will fail, let's set LANG in a hope,
786 # that UI will use it GRASS texts will be in selected language,
787 # system messages (i.e. OK, Cancel etc.) - in system default
788 # language
789 os.environ['LANGUAGE'] = language
790 os.environ['LANG'] = language
791
792 try:
793 locale.setlocale(locale.LC_ALL, language)
794 except locale.Error, e:
795 try:
796 # Locale lang.encoding might be missing. Let's try
797 # UTF-8 encoding before giving up as on Linux systems
798 # lang.UTF-8 locales are more common than legacy
799 # ISO-8859 ones.
800 language = locale.normalize('%s.UTF-8' % (language))
801 locale.setlocale(locale.LC_ALL, language)
802 except locale.Error, e:
803 # The last attempt...
804 try:
805 language = locale.normalize('%s.%s' % (language, locale.getpreferredencoding()))
806 locale.setlocale(locale.LC_ALL, language)
807 except locale.Error, e:
808 # If we got so far, attempts to set up language and locale have failed
809 # on this system
810 sys.stderr.write("Failed to enforce user specified language '%s' with error: '%s'\n" % (language, e))
811 sys.stderr.write("A LANGUAGE environmental variable has been set.\nPart of messages will be displayed in the requested language.\n")
812 return
813
814 # Set up environment for subprocesses
815 for lc in ('LC_CTYPE', 'LC_MESSAGES', 'LC_TIME', 'LC_COLLATE',
816 'LC_MONETARY', 'LC_PAPER', 'LC_NAME', 'LC_ADDRESS',
817 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION'):
818 os.environ[lc] = language
819
820 # Some code in GRASS might not like other decimal separators than .
821 # Other potential sources for problems are: LC_TIME LC_CTYPE
822 locale.setlocale(locale.LC_NUMERIC, 'C')
823 os.environ['LC_NUMERIC'] = 'C'
824 if os.getenv('LC_ALL'):
825 del os.environ['LC_ALL'] # Remove LC_ALL to not override LC_NUMERIC
826
827 # From now on enforce the new language
828 gettext.install('grasslibs', os.path.join(gisbase, 'locale'), unicode=True)
829
830
831def check_lock():
832 global lockfile
833 if not os.path.exists(location):
834 fatal(_("Path '%s' doesn't exist") % location)
835
836 # Check for concurrent use
837 lockfile = os.path.join(location, ".gislock")
838 ret = call([gfile("etc", "lock"), lockfile, "%d" % os.getpid()])
839 if ret == 0:
840 msg = None
841 elif ret == 2:
842 msg = _("%(user)s is currently running GRASS in selected mapset (" \
843 "file %(file)s found). Concurrent use not allowed." % {
844 'user': user, 'file': lockfile})
845 else:
846 msg = _("Unable to properly access '%s'.\n"
847 "Please notify system personel.") % lockfile
848
849 if msg:
850 if grass_gui == "wxpython":
851 thetest = call([os.getenv('GRASS_PYTHON'),
852 os.path.join(wxpython_base, "gis_set_error.py"),
853 msg])
854 else:
855 global remove_lockfile
856 remove_lockfile = False
857 fatal(msg)
858
859
860def make_fontcap():
861 fc = os.getenv('GRASS_FONT_CAP')
862 if fc and not os.access(fc, os.R_OK):
863 message(_("Building user fontcap..."))
864 call(["g.mkfontcap"])
865
866
867def check_shell():
868 global sh, shellname, grass_env_file
869 # cygwin has many problems with the shell setup
870 # below, so i hardcoded everything here.
871 if os.getenv('CYGWIN'):
872 sh = "cygwin"
873 shellname = "GNU Bash (Cygwin)"
874 os.environ['SHELL'] = "/usr/bin/bash.exe"
875 os.environ['OSTYPE'] = "cygwin"
876 else:
877 sh = os.path.basename(os.getenv('SHELL'))
878 if windows and sh:
879 sh = os.path.splitext(sh)[0]
880
881 if sh == "ksh":
882 shellname = "Korn Shell"
883 elif sh == "csh":
884 shellname = "C Shell"
885 elif sh == "tcsh":
886 shellname = "TC Shell"
887 elif sh == "bash":
888 shellname = "Bash Shell"
889 elif sh == "sh":
890 shellname = "Bourne Shell"
891 elif sh == "zsh":
892 shellname = "Z Shell"
893 elif sh == "cmd":
894 shellname = "Command Shell"
895 else:
896 shellname = "shell"
897
898 if sh in ['csh', 'tcsh']:
899 grass_env_file = os.path.join(grass_config_dir, 'cshrc')
900 elif sh in ['bash', 'msh', 'cygwin', 'sh']:
901 grass_env_file = os.path.join(grass_config_dir, 'bashrc')
902 elif sh == 'zsh':
903 grass_env_file = os.path.join(grass_config_dir, 'zshrc')
904 elif sh == 'cmd':
905 grass_env_file = os.path.join(grass_config_dir, 'env.bat')
906 else:
907 grass_env_file = os.path.join(grass_config_dir, 'bashrc')
908 warning(_("Unsupported shell <%(sh)s>: %(env)s") % {'sh': sh,
909 'env': grass_env_file})
910
911 # check for SHELL
912 if not os.getenv('SHELL'):
913 fatal(_("The SHELL variable is not set"))
914
915
916def check_batch_job():
917 global batch_job
918 # hack to process batch jobs:
919 batch_job = os.getenv('GRASS_BATCH_JOB')
920 if batch_job:
921 # defined, but ...
922 if not os.access(batch_job, os.F_OK):
923 # wrong file
924 fatal(_("Job file '%s' has been defined in "
925 "the 'GRASS_BATCH_JOB' variable but not found. Exiting.\n\n"
926 "Use 'unset GRASS_BATCH_JOB' to disable batch job processing.") % batch_job)
927 elif not os.access(batch_job, os.X_OK):
928 # right file, but ...
929 fatal(_("Change file permission to 'executable' for '%s'") % batch_job)
930 else:
931 message(_("Executing '%s' ...") % batch_job)
932 grass_gui = "text"
933 shell = batch_job
934 bj = Popen(shell, shell=True)
935 bj.wait()
936 message(_("Execution of '%s' finished.") % batch_job)
937
938
939def start_gui():
940 # Start the chosen GUI but ignore text
941 if grass_debug:
942 message(_("GRASS GUI should be <%s>") % grass_gui)
943
944 # Check for gui interface
945 if grass_gui == "wxpython":
946 Popen([os.getenv('GRASS_PYTHON'), gfile(wxpython_base, "wxgui.py")])
947
948
949def clear_screen():
950 if windows:
951 pass
952 # TODO: uncomment when PDCurses works.
953 # cls
954 else:
955 if not os.getenv('GRASS_BATCH_JOB') and not grass_debug:
956 call(["tput", "clear"])
957
958
959def show_banner():
960 sys.stderr.write(r"""
961 __________ ___ __________ _______________
962 / ____/ __ \/ | / ___/ ___/ / ____/ _/ ___/
963 / / __/ /_/ / /| | \__ \\_ \ / / __ / / \__ \
964 / /_/ / _, _/ ___ |___/ /__/ / / /_/ // / ___/ /
965 \____/_/ |_/_/ |_/____/____/ \____/___//____/
966
967""")
968
969
970def say_hello():
971 sys.stderr.write(_("Welcome to GRASS %s") % grass_version)
972
973
974def show_info():
975 sys.stderr.write(
976r"""
977%-41shttp://grass.osgeo.org
978%-41s%s (%s)
979%-41sg.manual -i
980%-41sg.version -c
981""" % (_("GRASS homepage:"),
982 _("This version running through:"),
983 shellname, os.getenv('SHELL'),
984 _("Help is available with the command:"),
985 _("See the licence terms with:")))
986
987 if grass_gui == 'wxpython':
988 message("%-41sg.gui wxpython" % _("If required, restart the GUI with:"))
989 else:
990 message("%-41sg.gui %s" % (_("Start the GUI with:"), default_gui))
991
992 message("%-41sexit" % _("When ready to quit enter:"))
993 message("")
994
995
996def csh_startup():
997 global exit_val
998
999 userhome = os.getenv('HOME') # save original home
1000 home = location
1001 os.environ['HOME'] = home
1002
1003 cshrc = os.path.join(home, ".cshrc")
1004 tcshrc = os.path.join(home, ".tcshrc")
1005 try_remove(cshrc)
1006 try_remove(tcshrc)
1007
1008 f = open(cshrc, 'w')
1009 f.write("set home = %s\n" % userhome)
1010 f.write("set history = 3000 savehist = 3000 noclobber ignoreeof\n")
1011 f.write("set histfile = %s\n" % os.path.join(os.getenv('HOME'),
1012 ".history"))
1013
1014 f.write("set prompt = '\\\n")
1015 f.write("Mapset <%s> in Location <%s> \\\n" % (mapset, location_name))
1016 f.write("GRASS %s > '\n" % grass_version)
1017 f.write("set BOGUS=``;unset BOGUS\n")
1018
1019 path = os.path.join(userhome, ".grass.cshrc") # left for backward compatibility
1020 if os.access(path, os.R_OK):
1021 f.write(readfile(path) + '\n')
1022 if os.access(grass_env_file, os.R_OK):
1023 f.write(readfile(grass_env_file) + '\n')
1024
1025 mail_re = re.compile(r"^ *set *mail *= *")
1026
1027 for filename in [".cshrc", ".tcshrc", ".login"]:
1028 path = os.path.join(userhome, filename)
1029 if os.access(path, os.R_OK):
1030 s = readfile(path)
1031 lines = s.splitlines()
1032 for l in lines:
1033 if mail_re.match(l):
1034 f.write(l)
1035
1036 path = os.getenv('PATH').split(':')
1037 f.write("set path = ( %s ) \n" % ' '.join(path))
1038
1039 f.close()
1040 writefile(tcshrc, readfile(cshrc))
1041
1042 exit_val = call([gfile("etc", "run"), os.getenv('SHELL')])
1043
1044 os.environ['HOME'] = userhome
1045
1046
1047def bash_startup():
1048 global exit_val
1049
1050 # save command history in mapset dir and remember more
1051 os.environ['HISTFILE'] = os.path.join(location, ".bash_history")
1052 if not os.getenv('HISTSIZE') and not os.getenv('HISTFILESIZE'):
1053 os.environ['HISTSIZE'] = "3000"
1054
1055 # instead of changing $HOME, start bash with: --rcfile "$LOCATION/.bashrc" ?
1056 # if so, must care be taken to explicity call .grass.bashrc et al for
1057 # non-interactive bash batch jobs?
1058 userhome = os.getenv('HOME') # save original home
1059 home = location # save .bashrc in $LOCATION
1060 os.environ['HOME'] = home
1061
1062 bashrc = os.path.join(home, ".bashrc")
1063 try_remove(bashrc)
1064
1065 f = open(bashrc, 'w')
1066 f.write("test -r ~/.alias && . ~/.alias\n")
1067 if os.getenv('ISISROOT'):
1068 f.write("PS1='ISIS-GRASS %s (%s):\w > '\n" % (grass_version, location_name))
1069 else:
1070 f.write("PS1='GRASS %s (%s):\w > '\n" % (grass_version, location_name))
1071
1072 f.write("PROMPT_COMMAND=\"'%s'\"\n" % os.path.join(gisbase, 'etc',
1073 'prompt.py'))
1074
1075 # read environmental variables
1076 path = os.path.join(userhome, ".grass.bashrc") # left for backward compatibility
1077 if os.access(path, os.R_OK):
1078 f.write(readfile(path) + '\n')
1079 if os.access(grass_env_file, os.R_OK):
1080 f.write(readfile(grass_env_file) + '\n')
1081
1082 f.write("export PATH=\"%s\"\n" % os.getenv('PATH'))
1083 f.write("export HOME=\"%s\"\n" % userhome) # restore user home path
1084
1085 f.close()
1086
1087 exit_val = call([gfile("etc", "run"), os.getenv('SHELL')])
1088
1089 os.environ['HOME'] = userhome
1090
1091
1092def default_startup():
1093 global exit_val
1094
1095 if windows:
1096 os.environ['PS1'] = "GRASS %s> " % (grass_version)
1097 # "$ETC/run" doesn't work at all???
1098 exit_val = subprocess.call([os.getenv('SHELL')])
1099 cleanup_dir(os.path.join(location, ".tmp")) # remove GUI session files from .tmp
1100 else:
1101 os.environ['PS1'] = "GRASS %s (%s):\w > " % (grass_version, location_name)
1102 exit_val = call([gfile("etc", "run"), os.getenv('SHELL')])
1103
1104 if exit_val != 0:
1105 fatal(_("Failed to start shell '%s'") % os.getenv('SHELL'))
1106
1107
1108def done_message():
1109 if batch_job and os.access(batch_job, os.X_OK):
1110 message(_("Batch job '%s' (defined in GRASS_BATCH_JOB variable) was executed.") % batch_job)
1111 message(_("Goodbye from GRASS GIS"))
1112 sys.exit(exit_val)
1113 else:
1114 message(_("Done."))
1115 message("")
1116 message(_("Goodbye from GRASS GIS"))
1117 message("")
1118
1119
1120def clean_temp():
1121 message(_("Cleaning up temporary files..."))
1122 nul = open(os.devnull, 'w')
1123 call([gfile("etc", "clean_temp")], stdout=nul, stderr=nul)
1124 nul.close()
1125
1126
1127def grep(string,list):
1128 expr = re.compile(string)
1129 return [elem for elem in list if expr.match(elem)]
1130
1131
1132def print_params():
1133 plat = gfile(gisbase, 'include', 'Make', 'Platform.make')
1134 fileplat = open(plat)
1135 linesplat = fileplat.readlines()
1136 fileplat.close()
1137
1138 params = sys.argv[2:]
1139 if not params:
1140 params = ['arch', 'build', 'compiler', 'path', 'revision']
1141
1142 for arg in params:
1143 if arg == 'path':
1144 sys.stdout.write("%s\n" % gisbase)
1145 elif arg == 'arch':
1146 val = grep('ARCH',linesplat)
1147 sys.stdout.write("%s\n" % val[0].split('=')[1].strip())
1148 elif arg == 'build':
1149 build = os.path.join(gisbase,'include','grass','confparms.h')
1150 filebuild = open(build)
1151 val = filebuild.readline()
1152 filebuild.close()
1153 sys.stdout.write("%s\n" % val.strip().strip('"').strip())
1154 elif arg == 'compiler':
1155 val = grep('CC',linesplat)
1156 sys.stdout.write("%s\n" % val[0].split('=')[1].strip())
1157 elif arg == 'revision':
1158 rev = os.path.join(gisbase,'include','grass','gis.h')
1159 filerev = open(rev)
1160 linesrev = filerev.readlines()
1161 val = grep('#define GIS_H_VERSION', linesrev)
1162 filerev.close()
1163 sys.stdout.write("%s\n" % val[0].split(':')[1].rstrip('$"\n').strip())
1164 else:
1165 message(_("Parameter <%s> not supported") % arg)
1166
1167
1168def get_username():
1169 global user
1170 if windows:
1171 user = os.getenv('USERNAME')
1172 if not user:
1173 user = "user_name"
1174 else:
1175 user = os.getenv('USER')
1176 if not user:
1177 user = os.getenv('LOGNAME')
1178 if not user:
1179 try:
1180 p = Popen(['whoami'], stdout = subprocess.PIPE)
1181 s = p.stdout.read()
1182 p.wait()
1183 user = s.strip()
1184 except:
1185 pass
1186 if not user:
1187 user = "user_%d" % os.getuid()
1188
1189
1190def parse_cmdline():
1191 global args, grass_gui, create_new
1192 args = []
1193 for i in sys.argv[1:]:
1194 # Check if the user asked for the version
1195 if i in ["-v", "--version"]:
1196 message('\n' + readfile(gfile("etc", "license")))
1197 sys.exit()
1198 # Check if the user asked for help
1199 elif i in ["help", "-h", "-help", "--help"]:
1200 help_message()
1201 sys.exit()
1202 # Check if the -text flag was given
1203 elif i in ["-text", "--text"]:
1204 grass_gui = 'text'
1205 # Check if the -gui flag was given
1206 elif i in ["-gui", "--gui"]:
1207 grass_gui = default_gui
1208 # Check if the -wxpython flag was given
1209 elif i in ["-wxpython", "-wx", "--wxpython", "--wx"]:
1210 grass_gui = 'wxpython'
1211 # Check if the user wants to create a new mapset
1212 elif i == "-c":
1213 create_new = True
1214 elif i == "--config":
1215 print_params()
1216 sys.exit()
1217 else:
1218 args.append(i)
1219
1220### MAIN script starts here
1221
1222# Get the system name
1223windows = sys.platform == 'win32'
1224cygwin = "cygwin" in sys.platform
1225macosx = "darwin" in sys.platform
1226
1227if 'GISBASE' in os.environ:
1228 sys.exit(_("ERROR: GRASS GIS seems to be already running. Exiting."))
1229
1230# Set GISBASE
1231os.environ['GISBASE'] = gisbase
1232
1233# set HOME
1234if windows and not os.getenv('HOME'):
1235 os.environ['HOME'] = os.path.join(os.getenv('HOMEDRIVE'),
1236 os.getenv('HOMEPATH'))
1237
1238# set SHELL
1239if windows:
1240 if os.getenv('GRASS_SH'):
1241 os.environ['SHELL'] = os.getenv('GRASS_SH')
1242 if not os.getenv('SHELL'):
1243 os.environ['SHELL'] = os.getenv('COMSPEC', 'cmd.exe')
1244
1245atexit.register(cleanup)
1246
1247# Set default GUI
1248default_gui = "wxpython"
1249
1250# the following is only meant to be an internal variable for debugging this
1251# script. use 'g.gisenv set="DEBUG=[0-5]"' to turn GRASS debug mode on properly
1252grass_debug = os.getenv('GRASS_DEBUG')
1253
1254# Set GRASS version number for R interface etc (must be an env_var for MS-Windows)
1255os.environ['GRASS_VERSION'] = grass_version
1256
1257# Set the GIS_LOCK variable to current process id
1258gis_lock = str(os.getpid())
1259os.environ['GIS_LOCK'] = gis_lock
1260
1261if not os.path.exists(grass_config_dir):
1262 os.mkdir(grass_config_dir)
1263
1264# Set the global grassrc file
1265batch_job = os.getenv('GRASS_BATCH_JOB')
1266if batch_job:
1267 gisrcrc = os.path.join(grass_config_dir, "rc.%s" % platform.node())
1268 if not os.access(gisrcrc, os.R_OK):
1269 gisrcrc = os.path.join(grass_config_dir, "rc")
1270else:
1271 gisrcrc = os.path.join(grass_config_dir, "rc")
1272
1273# Set the username and working directory
1274get_username()
1275
1276# Parse the command-line options
1277parse_cmdline()
1278
1279# Set language
1280# This has to be called before any _() function call!
1281# Subsequent functions are using _() calls and
1282# thus must be called only after Language has been set.
1283set_language()
1284
1285# Create the temporary directory and session grassrc file
1286create_tmp()
1287
1288# Create the session grassrc file
1289create_gisrc()
1290
1291# Set shell (needs to be called before load_env())
1292check_shell()
1293
1294# Load environmental variables from the file
1295load_env()
1296
1297# Ensure GUI is set
1298read_gui()
1299
1300# Set PATH, PYTHONPATH
1301set_paths()
1302
1303# Set LD_LIBRARY_PATH (etc) to find GRASS shared libraries
1304path_prepend(gfile("lib"), ld_library_path_var)
1305
1306# Set GRASS_PAGER, GRASS_PYTHON, GRASS_GNUPLOT, GRASS_PROJSHARE
1307set_defaults()
1308
1309# Set GRASS_HTML_BROWSER
1310set_browser()
1311
1312#predefine monitor size for certain architectures
1313if os.getenv('HOSTTYPE') == 'arm':
1314 # small monitor on ARM (iPAQ, zaurus... etc)
1315 os.environ['GRASS_HEIGHT'] = "320"
1316 os.environ['GRASS_WIDTH'] = "240"
1317
1318# First time user - GISRC is defined in the GRASS script
1319if not os.access(gisrc, os.F_OK):
1320 if grass_gui == 'text' and len(args) == 0:
1321 fatal(_("Unable to start GRASS. You can:\n"
1322 " - Launch GRASS with '-gui' switch (`grass70 -gui`)\n"
1323 " - Create manually GISRC file (%s)\n"
1324 " - Launch GRASS with path to "
1325 "the location/mapset as an argument (`grass70 /path/to/location/mapset`)") % gisrcrc)
1326 grass_intro()
1327else:
1328 clean_temp()
1329
1330message(_("Starting GRASS GIS..."))
1331
1332# Check that the GUI works
1333check_gui()
1334
1335# Parsing argument to get LOCATION
1336if not args:
1337 # Try interactive startup
1338 location = None
1339else:
1340 if create_new:
1341 if len(args) > 1:
1342 non_interactive(args[1], args[0])
1343 else:
1344 non_interactive(args[0])
1345 else:
1346 non_interactive(args[0])
1347
1348# User selects LOCATION and MAPSET if not set
1349set_data()
1350
1351# Set GISDBASE, LOCATION_NAME, MAPSET, LOCATION from $GISRC
1352load_gisrc()
1353
1354# Check .gislock file
1355check_lock()
1356
1357# build user fontcap if specified but not present
1358make_fontcap()
1359
1360# predefine default driver if DB connection not defined
1361# is this really needed?? Modules should call this when/if required.
1362if not os.access(os.path.join(location, "VAR"), os.F_OK):
1363 call(['db.connect', '-c', '--quiet'])
1364
1365check_batch_job()
1366
1367if not batch_job:
1368 start_gui()
1369
1370clear_screen()
1371
1372# Display the version and license info
1373if batch_job:
1374 grass_gui = 'text'
1375 clear_screen()
1376 clean_temp()
1377 try_remove(lockfile)
1378 sys.exit(0)
1379else:
1380 show_banner()
1381 say_hello()
1382 show_info()
1383 if grass_gui == "wxpython":
1384 message(_("Launching <%s> GUI in the background, please wait...") % grass_gui)
1385
1386if sh in ['csh', 'tcsh']:
1387 csh_startup()
1388elif sh in ['bash', 'msh', 'cygwin']:
1389 bash_startup()
1390else:
1391 default_startup()
1392
1393clear_screen()
1394
1395clean_env()
1396clean_temp()
1397
1398try_remove(lockfile)
1399
1400# Save GISRC
1401s = readfile(gisrc)
1402writefile(gisrcrc, s)
1403
1404cleanup()
1405
1406# After this point no more grass modules may be called
1407
1408done_message()
Note: See TracBrowser for help on using the repository browser.