grass.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. #!/usr/bin/env python
  2. #############################################################################
  3. #
  4. # MODULE: GRASS initialization (Python)
  5. # AUTHOR(S): Original author unknown - probably CERL
  6. # Andreas Lange - Germany - andreas.lange at rhein-main.de
  7. # Huidae Cho - Korea - grass4u at gmail.com
  8. # Justin Hickey - Thailand - jhickey at hpcc.nectec.or.th
  9. # Markus Neteler - Germany/Italy - neteler at itc.it
  10. # Hamish Bowman - New Zealand - hamish_b at yahoo,com
  11. # Converted to Python (based on init.sh) by Glynn Clements
  12. # Martin Landa - Czech Republic - landa.martin at gmail.com
  13. # PURPOSE: Sets up some environment variables.
  14. # It also parses any remaining command line options for
  15. # setting the GISDBASE, LOCATION, and/or MAPSET.
  16. # Finally it starts GRASS with the appropriate user
  17. # interface and cleans up after it is finished.
  18. # COPYRIGHT: (C) 2000-2010 by the GRASS Development Team
  19. #
  20. # This program is free software under the GNU General
  21. # Public License (>=v2). Read the file COPYING that
  22. # comes with GRASS for details.
  23. #
  24. #############################################################################
  25. import sys
  26. import os
  27. import atexit
  28. import string
  29. import subprocess
  30. import re
  31. # Variables substituted during build process
  32. # Set the GISBASE variable
  33. if os.getenv("GISBASE"):
  34. gisbase = os.getenv("GISBASE")
  35. else:
  36. gisbase = "@GISBASE@"
  37. cmd_name = "@START_UP@"
  38. grass_version = "@GRASS_VERSION_NUMBER@"
  39. ld_library_path_var = '@LD_LIBRARY_PATH_VAR@'
  40. if os.getenv("GRASS_PROJSHARE"):
  41. config_projshare = os.getenv("GRASS_PROJSHARE")
  42. else:
  43. config_projshare = "@CONFIG_PROJSHARE@"
  44. grass_config_dirname = "@GRASS_CONFIG_DIR@"
  45. gisbase = os.path.normpath(gisbase)
  46. tmpdir = None
  47. lockfile = None
  48. location = None
  49. create_new = None
  50. grass_gui = None
  51. def try_remove(path):
  52. try:
  53. os.remove(path)
  54. except:
  55. pass
  56. def try_rmdir(path):
  57. try:
  58. os.rmdir(path)
  59. except:
  60. pass
  61. def cleanup_dir(dir):
  62. if not dir:
  63. return
  64. for root, dirs, files in os.walk(dir, topdown = False):
  65. for name in files:
  66. try_remove(os.path.join(root, name))
  67. for name in dirs:
  68. try_rmdir(os.path.join(root, name))
  69. def cleanup():
  70. tmpdir, lockfile
  71. # all exits after setting up $tmpdir should also tidy it up
  72. cleanup_dir(tmpdir)
  73. if lockfile:
  74. try_remove(lockfile)
  75. def fatal(msg):
  76. sys.exit(msg)
  77. def message(msg):
  78. sys.stderr.write(msg + "\n")
  79. def readfile(path):
  80. f = open(path, 'r')
  81. s = f.read()
  82. f.close()
  83. return s
  84. def writefile(path, s):
  85. f = open(path, 'w')
  86. f.write(s)
  87. f.close()
  88. def call(cmd, **kwargs):
  89. if windows:
  90. kwargs['shell'] = True
  91. return subprocess.call(cmd, **kwargs)
  92. def gfile(*args):
  93. return os.path.join(gisbase, *args)
  94. help_text = r"""
  95. Usage:
  96. $CMD_NAME [-h | -help | --help] [-v | --version] [-c]
  97. [-text | -gui | -wxpython | -wx]
  98. [[[<GISDBASE>/]<LOCATION_NAME>/]<MAPSET>]
  99. Flags:
  100. -h or -help or --help print this help message
  101. -v or --version show version information and exit
  102. -c create given mapset if it doesn\'t exist
  103. -text use text based interface
  104. and set as default
  105. -gui use graphical user interface ($DEFAULT_GUI by default)
  106. and set as default
  107. -wxpython or -wx use wxPython based graphical user interface
  108. and set as default
  109. Parameters:
  110. GISDBASE initial database (path to GIS data)
  111. LOCATION_NAME initial location
  112. MAPSET initial mapset
  113. GISDBASE/LOCATION_NAME/MAPSET fully qualified initial mapset directory
  114. Environment variables relevant for startup:
  115. GRASS_GUI select GUI (text, gui, wxpython)
  116. GRASS_WISH set wish shell name to override 'wish'
  117. GRASS_HTML_BROWSER set html web browser for help pages
  118. GRASS_ADDON_PATH set additional path(s) to local GRASS modules
  119. GRASS_BATCH_JOB shell script to be processed as batch job
  120. GRASS_PYTHON set python shell name to override 'python'
  121. """
  122. def help_message():
  123. t = string.Template(help_text)
  124. s = t.substitute(CMD_NAME = cmd_name, DEFAULT_GUI = default_gui)
  125. sys.stderr.write(s)
  126. def create_tmp():
  127. global tmpdir
  128. ## use $TMPDIR if it exists, then $TEMP, otherwise /tmp
  129. tmp = os.getenv('TMPDIR')
  130. if not tmp:
  131. tmp = os.getenv('TEMP')
  132. if not tmp:
  133. tmp = '/tmp'
  134. tmpdir = os.path.join(tmp, "grass7-%s-%s" % (user, gis_lock))
  135. try:
  136. os.mkdir(tmpdir, 0700)
  137. except:
  138. fatal("Cannot create temporary directory! Exiting.")
  139. def create_gisrc():
  140. global gisrc, gisrcrc
  141. # Set the session grassrc file
  142. gisrc = os.path.join(tmpdir, "gisrc")
  143. os.environ['GISRC'] = gisrc
  144. # remove invalid GISRC file to avoid disturbing error messages:
  145. try:
  146. s = readfile(gisrcrc)
  147. if "UNKNOWN" in s:
  148. try_remove(gisrcrc)
  149. s = None
  150. except:
  151. s = None
  152. # Copy the global grassrc file to the session grassrc file
  153. if s:
  154. writefile(gisrc, s)
  155. def read_gisrc():
  156. kv = {}
  157. f = open(gisrc, 'r')
  158. for line in f:
  159. k, v = line.split(':', 1)
  160. kv[k.strip()] = v.strip()
  161. f.close()
  162. return kv
  163. def write_gisrc(kv):
  164. f = open(gisrc, 'w')
  165. for k, v in kv.iteritems():
  166. f.write("%s: %s\n" % (k, v))
  167. f.close()
  168. def read_gui():
  169. global grass_gui
  170. # At this point the GRASS user interface variable has been set from the
  171. # command line, been set from an external environment variable, or is
  172. # not set. So we check if it is not set
  173. if not grass_gui:
  174. # Check for a reference to the GRASS user interface in the grassrc file
  175. if os.access(gisrc, os.R_OK):
  176. kv = read_gisrc()
  177. if not kv.has_key('GRASS_GUI'):
  178. # Set the GRASS user interface to the default if needed
  179. grass_gui = default_gui
  180. else:
  181. grass_gui = kv['GRASS_GUI']
  182. if not grass_gui:
  183. grass_gui = default_gui
  184. if grass_gui == 'gui':
  185. grass_gui = default_gui
  186. # FIXME oldtcltk, gis.m, d.m no longer exist
  187. if grass_gui in ['d.m', 'gis.m', 'oldtcltk', 'tcltk']:
  188. grass_gui = default_gui
  189. def get_locale():
  190. global locale
  191. locale = None
  192. for var in ['LC_ALL', 'LC_MESSAGES', 'LANG']:
  193. loc = os.getenv(var)
  194. if loc:
  195. locale = loc[0:2]
  196. return
  197. def path_prepend(dir, var):
  198. path = os.getenv(var)
  199. if path:
  200. path = dir + os.pathsep + path
  201. else:
  202. path = dir
  203. os.environ[var] = path
  204. def path_append(dir, var):
  205. path = os.getenv(var)
  206. if path:
  207. path = path + os.pathsep + dir
  208. else:
  209. path = dir
  210. os.environ[var] = path
  211. def set_paths():
  212. addon_path = os.getenv('GRASS_ADDON_PATH')
  213. if addon_path:
  214. path_prepend(addon_path, 'PATH')
  215. path_prepend(gfile('scripts'), 'PATH')
  216. path_prepend(gfile('bin'), 'PATH')
  217. # Set PYTHONPATH to find GRASS Python modules
  218. path_prepend(gfile('etc', 'python'), 'PYTHONPATH')
  219. # Add .py (Python) to list of executable extensions to search for in MS-Windows PATH
  220. if windows:
  221. path_append('.PY', 'PATHEXT')
  222. def find_exe(pgm):
  223. for dir in os.getenv('PATH').split(os.pathsep):
  224. path = os.path.join(dir, pgm)
  225. if os.access(path, os.X_OK):
  226. return path
  227. return None
  228. def set_defaults():
  229. # GRASS_PAGER
  230. if not os.getenv('GRASS_PAGER'):
  231. if find_exe("more"):
  232. pager = "more"
  233. elif find_exe("less"):
  234. pager = "less"
  235. elif windows:
  236. pager = "more"
  237. else:
  238. pager = "cat"
  239. os.environ['GRASS_PAGER'] = pager
  240. # GRASS_WISH
  241. if not os.getenv('GRASS_WISH'):
  242. os.environ['GRASS_WISH'] = "wish"
  243. # GRASS_PYTHON
  244. if not os.getenv('GRASS_PYTHON'):
  245. if windows:
  246. os.environ['GRASS_PYTHON'] = "python.exe"
  247. else:
  248. os.environ['GRASS_PYTHON'] = "python"
  249. # GRASS_GNUPLOT
  250. if not os.getenv('GRASS_GNUPLOT'):
  251. os.environ['GRASS_GNUPLOT'] = "gnuplot -persist"
  252. # GRASS_PROJSHARE
  253. if not os.getenv('GRASS_PROJSHARE'):
  254. os.environ['GRASS_PROJSHARE'] = config_projshare
  255. def set_browser():
  256. # GRASS_HTML_BROWSER
  257. browser = os.getenv('GRASS_HTML_BROWSER')
  258. if not browser:
  259. if macosx:
  260. # OSX doesn't execute browsers from the shell PATH - route thru a script
  261. browser = gfile('etc', "html_browser_mac.sh")
  262. os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b com.apple.helpviewer"
  263. if windows or cygwin:
  264. # MinGW startup moved to into init.bat
  265. iexplore = os.path.join(os.getenv('ProgramFiles'), "Internet Explorer", "iexplore.exe")
  266. if os.access(iexplore, os.F_OK):
  267. browser = iexplore
  268. else:
  269. browser = "iexplore"
  270. else:
  271. # the usual suspects
  272. browsers = [ "htmlview", "konqueror", "mozilla", "mozilla-firefox",
  273. "firefox", "iceweasel", "opera", "netscape", "dillo" ]
  274. for b in browsers:
  275. if find_exe(b):
  276. browser = b
  277. break
  278. if macosx and browser:
  279. # OSX doesn't execute browsers from the shell PATH - route thru a script
  280. browser = gfile('etc', "html_browser_mac.sh")
  281. os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b com.apple.helpviewer"
  282. if not browser:
  283. message("WARNING: Searched for a web browser, but none found.")
  284. # even so we set konqueror to make lib/gis/parser.c happy:
  285. browser = "konqueror"
  286. os.environ['GRASS_HTML_BROWSER'] = browser
  287. def grass_intro():
  288. if locale:
  289. path = gfile("locale", locale, "etc", "grass_intro")
  290. if not os.access(path, os.R_OK):
  291. path = gfile("etc", "grass_intro")
  292. else:
  293. path = gfile("etc", "grass_intro")
  294. f = open(path, 'r')
  295. for line in f:
  296. sys.stderr.write(line)
  297. f.close()
  298. sys.stderr.write("\n")
  299. sys.stderr.write("Hit RETURN to continue")
  300. sys.stdin.readline()
  301. #for convenience, define pwd as GISDBASE:
  302. s = r"""GISDBASE: %s
  303. LOCATION_NAME: <UNKNOWN>
  304. MAPSET: <UNKNOWN>
  305. """ % os.getcwd()
  306. writefile(gisrc, s)
  307. def check_gui():
  308. global grass_gui, wxpython_base
  309. # Check if we are running X windows by checking the DISPLAY variable
  310. if os.getenv('DISPLAY') or windows:
  311. # Check if python is working properly
  312. if grass_gui == 'wxpython':
  313. nul = open(os.devnull, 'w')
  314. p = subprocess.Popen([os.environ['GRASS_PYTHON']],
  315. stdin = subprocess.PIPE,
  316. stdout = nul, stderr = nul)
  317. nul.close()
  318. p.stdin.write("variable=True")
  319. p.stdin.close()
  320. p.wait()
  321. if p.returncode == 0:
  322. # Set the wxpython base directory
  323. wxpython_base = gfile("etc", "gui", "wxpython")
  324. else:
  325. # Python was not found - switch to text interface mode
  326. message(
  327. r"""WARNING: The python command does not work as expected!
  328. Please check your GRASS_PYTHON environment variable.
  329. Use the -help option for details.
  330. Switching to text based interface mode.
  331. Hit RETURN to continue.""")
  332. sys.stdin.readline()
  333. grass_gui = 'text'
  334. else:
  335. # Display a message if a graphical interface was expected
  336. if grass_gui != 'text':
  337. # Set the interface mode to text
  338. message(
  339. r"""WARNING: It appears that the X Windows system is not active.
  340. A graphical based user interface is not supported.
  341. Switching to text based interface mode.
  342. Hit RETURN to continue""")
  343. sys.stdin.readline()
  344. grass_gui = 'text'
  345. # Save the user interface variable in the grassrc file - choose a temporary
  346. # file name that should not match another file
  347. if os.access(gisrc, os.F_OK):
  348. kv = read_gisrc()
  349. kv['GRASS_GUI'] = grass_gui
  350. write_gisrc(kv)
  351. def non_interactive(arg):
  352. global gisdbase, location_name, mapset, location
  353. # Try non-interactive startup
  354. l = None
  355. if arg == '-':
  356. if location:
  357. l = location
  358. else:
  359. l = arg
  360. if l:
  361. if l == '.':
  362. l = os.getcwd()
  363. elif not os.path.isabs(l):
  364. l = os.path.abspath(l)
  365. l, mapset = os.path.split(l)
  366. if not mapset:
  367. l, mapset = os.path.split(l)
  368. l, location_name = os.path.split(l)
  369. gisdbase = l
  370. if gisdbase and location_name and mapset:
  371. location = os.path.join(gisdbase, location_name, mapset)
  372. if not os.access(os.path.join(location, "WIND"), os.R_OK):
  373. if location_name == "PERMANENT":
  374. fatal("%s: Not a valid GRASS location" % location)
  375. else:
  376. # the user wants to create mapset on the fly
  377. if create_new:
  378. if not os.access(os.path.join(os.path.join(gisdbase, location_name, "PERMANENT", "DEFAULT_WIND")), os.F_OK):
  379. fatal("The LOCATION \"%s\" does not exist. Please create it first" % location_name)
  380. else:
  381. os.mkdirs(location)
  382. # copy PERMANENT/DEFAULT_WIND to <mapset>/WIND
  383. s = readfile(os.path.join(gisdbase, location_name, "PERMANENT", "DEFAULT_WIND"))
  384. writefile(os.path.join(location, "WIND"), s)
  385. message("Missing WIND file fixed")
  386. else:
  387. fatal("%s: Not a valid GRASS location" % location)
  388. if os.access(gisrc, os.R_OK):
  389. kv = read_gisrc()
  390. else:
  391. kv = {}
  392. kv['GISDBASE'] = gisdbase
  393. kv['LOCATION_NAME'] = location_name
  394. kv['MAPSET'] = mapset
  395. write_gisrc(kv)
  396. else:
  397. fatal("GISDBASE, LOCATION_NAME and MAPSET variables not set properly.\n" +
  398. "Interactive startup needed.")
  399. def set_data():
  400. # User selects LOCATION and MAPSET if not set
  401. if not location:
  402. # Check for text interface
  403. if grass_gui == 'text':
  404. pass
  405. # Check for GUI
  406. elif grass_gui == 'wxpython':
  407. gui_startup()
  408. else:
  409. # Shouldn't need this but you never know
  410. fatal("ERROR: Invalid user interface specified - <%s>.\n" % grass_gui +
  411. "Use the --help option to see valid interface names.")
  412. def gui_startup():
  413. if grass_gui == 'wxpython':
  414. thetest = call([os.getenv('GRASS_PYTHON'), os.path.join(wxpython_base, "gis_set.py")])
  415. if thetest == 0:
  416. pass
  417. elif thetest == 1:
  418. # The startup script printed an error message so wait
  419. # for user to read it
  420. message(
  421. r"""
  422. Error in GUI startup. If necessary, please
  423. report this error to the GRASS developers.
  424. Switching to text mode now.
  425. Hit RETURN to continue...""")
  426. sys.stdin.readline()
  427. os.execlp(cmd_name, "-text")
  428. sys.exit(1)
  429. elif thetest == 2:
  430. # User wants to exit from GRASS
  431. message("Received EXIT message from GUI.\n" + "GRASS is not started. Bye.")
  432. sys.exit(0)
  433. else:
  434. fatal("ERROR: Invalid return code from GUI startup script.\n" +
  435. "Please advise GRASS developers of this error.")
  436. def load_gisrc():
  437. global gisdbase, location_name, mapset, location
  438. kv = read_gisrc()
  439. gisdbase = kv.get('GISDBASE')
  440. location_name = kv.get('LOCATION_NAME')
  441. mapset = kv.get('MAPSET')
  442. if not gisdbase or not location_name or not mapset:
  443. message(
  444. r"""ERROR: Reading data path information from g.gisenv.
  445. GISDBASE=[%s]
  446. LOCATION_NAME=[%s]
  447. MAPSET=[%s]
  448. Check the <%s> file.""" % (gisdbase, location_name, mapset, gisrcrc))
  449. sys.exit(1)
  450. location = os.path.join(gisdbase, location_name, mapset)
  451. def check_lock():
  452. global lockfile
  453. # Check for concurrent use
  454. lockfile = os.path.join(location, ".gislock")
  455. ret = call([gfile("etc", "lock"),
  456. lockfile,
  457. "%d" % os.getpid()])
  458. if ret == 0:
  459. msg = None
  460. elif ret == 2:
  461. msg = "%s is currently running GRASS in selected mapset (file %s found). " \
  462. "Concurrent use not allowed." % \
  463. (user, lockfile)
  464. else:
  465. msg = "Unable to properly access \"%s\"\n" % \
  466. lockfile + "Please notify system personel."
  467. if msg:
  468. if grass_gui == "wxpython":
  469. thetest = call([os.getenv('GRASS_PYTHON'), os.path.join(wxpython_base, "gis_set_error.py"), msg])
  470. else:
  471. fatal(msg)
  472. def make_fontcap():
  473. fc = os.getenv('GRASS_FONT_CAP')
  474. if fc and not os.access(fc, os.R_OK):
  475. message("Building user fontcap ...")
  476. call(["g.mkfontcap"])
  477. def check_shell():
  478. global sh, shellname
  479. # cygwin has many problems with the shell setup
  480. # below, so i hardcoded everything here.
  481. if os.getenv('CYGWIN'):
  482. sh = "cygwin"
  483. shellname = "GNU Bash (Cygwin)"
  484. os.environ['SHELL'] = "/usr/bin/bash.exe"
  485. os.environ['OSTYPE'] = "cygwin"
  486. else:
  487. sh = os.path.basename(os.getenv('SHELL'))
  488. if sh == "ksh":
  489. shellname = "Korn Shell"
  490. elif sh == "csh":
  491. shellname = "C Shell"
  492. elif sh == "tcsh":
  493. shellname = "TC Shell"
  494. elif sh == "bash":
  495. shellname = "Bash Shell"
  496. elif sh == "sh":
  497. shellname = "Bourne Shell"
  498. else:
  499. shellname = "shell"
  500. # check for SHELL
  501. if not os.getenv('SHELL'):
  502. fatal("ERROR: The SHELL variable is not set")
  503. def check_batch_job():
  504. global batch_job
  505. # hack to process batch jobs:
  506. batch_job = os.getenv('GRASS_BATCH_JOB')
  507. if batch_job:
  508. # defined, but ...
  509. if not os.access(batch_job, os.F_OK):
  510. # wrong file
  511. fatal(
  512. r"""Job file '%s' has been defined in
  513. the 'GRASS_BATCH_JOB' variable but not found. Exiting.
  514. Use 'unset GRASS_BATCH_JOB' to disable batch job processing.
  515. """ % batch_job)
  516. elif not os.access(batch_job, os.X_OK):
  517. # right file, but ...
  518. fatal("ERROR: change file permission to 'executable' for '%s'" % batch_job)
  519. else:
  520. message("Executing '$GRASS_BATCH_JOB' ...")
  521. grass_gui = "text"
  522. shell = batch_job
  523. def start_gui():
  524. # Start the chosen GUI but ignore text
  525. if grass_debug:
  526. message("GRASS GUI should be %s" % grass_gui)
  527. # Check for gui interface
  528. if grass_gui == "wxpython":
  529. subprocess.Popen([os.getenv('GRASS_PYTHON'),
  530. gfile(wxpython_base, "wxgui.py")])
  531. def clear_screen():
  532. if windows:
  533. pass
  534. # TODO: uncomment when PDCurses works.
  535. # cls
  536. else:
  537. if not os.getenv('GRASS_BATCH_JOB') and not grass_debug:
  538. call(["tput", "clear"])
  539. def show_banner():
  540. sys.stderr.write(r"""
  541. __________ ___ __________ _______________
  542. / ____/ __ \/ | / ___/ ___/ / ____/ _/ ___/
  543. / / __/ /_/ / /| | \__ \\_ \ / / __ / / \__ \
  544. / /_/ / _, _/ ___ |___/ /__/ / / /_/ // / ___/ /
  545. \____/_/ |_/_/ |_/____/____/ \____/___//____/
  546. """)
  547. def say_hello():
  548. if locale:
  549. path = gfile("locale", locale, "etc", "welcome")
  550. if not os.access(path, os.R_OK):
  551. path = gfile("etc", "welcome")
  552. else:
  553. path = gfile("etc", "welcome")
  554. s = readfile(path)
  555. sys.stderr.write(s)
  556. def show_info():
  557. sys.stderr.write(
  558. r"""
  559. GRASS homepage: http://grass.osgeo.org/
  560. This version running through: %s (%s)
  561. Help is available with the command: g.manual -i
  562. See the licence terms with: g.version -c
  563. """ % (shellname, os.getenv('SHELL')))
  564. if grass_gui == 'wxpython':
  565. message("If required, restart the GUI with: g.gui wxpython")
  566. else:
  567. message("Start the GUI with: g.gui %s" % default_gui)
  568. message("When ready to quit enter: exit")
  569. message("")
  570. def csh_startup():
  571. global exit_val
  572. userhome = os.getenv('HOME') # save original home
  573. home = location
  574. os.environ['HOME'] = home
  575. cshrc = os.path.join(home, ".cshrc")
  576. tcshrc = os.path.join(home, ".tcshrc")
  577. try_remove(cshrc)
  578. try_remove(tcshrc)
  579. f = open(cshrc, 'w')
  580. f.write("set home = %s" % userhome)
  581. f.write("set history = 3000 savehist = 3000 noclobber ignoreeof")
  582. f.write("set histfile = %s" % os.path.join(os.getenv('HOME'), ".history"))
  583. f.write("set prompt = '\\")
  584. f.write("Mapset <%s> in Location <%s> \\" % (mapset, location_name))
  585. f.write("GRASS %s > '" % grass_version)
  586. f.write("set BOGUS=``;unset BOGUS")
  587. path = os.path.join(userhome, ".grass.cshrc")
  588. if os.access(path, os.R_OK):
  589. f.write(readfile(path))
  590. mail_re = re.compile(r"^ *set *mail *= *")
  591. for filename in [".cshrc", ".tcshrc", ".login"]:
  592. path = os.path.join(userhome, filename)
  593. if os.access(path, os.R_OK):
  594. s = readfile(path)
  595. lines = s.splitlines()
  596. for l in lines:
  597. if mail_re.match(l):
  598. f.write(l)
  599. path = os.getenv('PATH').split(':')
  600. f.write("set path = ( %s ) " % ' '.join(path))
  601. f.close()
  602. writefile(tcshrc, readfile(cshrc))
  603. exit_val = call([gfile("etc", "run"), os.getenv('SHELL')])
  604. os.environ['HOME'] = userhome
  605. def bash_startup():
  606. global exit_val
  607. # save command history in mapset dir and remember more
  608. os.environ['HISTFILE'] = os.path.join(location, ".bash_history")
  609. if not os.getenv('HISTSIZE') and not os.getenv('HISTFILESIZE'):
  610. os.environ['HISTSIZE'] = "3000"
  611. # instead of changing $HOME, start bash with: --rcfile "$LOCATION/.bashrc" ?
  612. # if so, must care be taken to explicity call .grass.bashrc et al for
  613. # non-interactive bash batch jobs?
  614. userhome = os.getenv('HOME') # save original home
  615. home = location # save .bashrc in $LOCATION
  616. os.environ['HOME'] = home
  617. bashrc = os.path.join(home, ".bashrc")
  618. try_remove(bashrc)
  619. f = open(bashrc, 'w')
  620. f.write("test -r ~/.alias && . ~/.alias\n")
  621. f.write("PS1='GRASS %s (%s):\w > '\n" % (grass_version, location_name))
  622. path = os.path.join(userhome, ".grass.bashrc")
  623. if os.access(path, os.R_OK):
  624. f.write(readfile(path) + '\n')
  625. f.write("export PATH=\"%s\"\n" % os.getenv('PATH'))
  626. f.write("export HOME=\"%s\"\n" % userhome) # restore user home path
  627. for env, value in os.environ.iteritems():
  628. if env.find('GRASS_') < 0:
  629. continue
  630. f.write("export %s=\"%s\"\n" % (env, value))
  631. f.close()
  632. exit_val = call([gfile("etc", "run"), os.getenv('SHELL')])
  633. os.environ['HOME'] = userhome
  634. def default_startup():
  635. global exit_val
  636. if windows:
  637. os.environ['PS1'] = "GRASS %s> " % (grass_version)
  638. # "$ETC/run" doesn't work at all???
  639. exit_val = call([os.getenv('SHELL')])
  640. cleanup_dir(os.path.join(location, ".tmp")) # remove GUI session files from .tmp
  641. else:
  642. os.environ['PS1'] = "GRASS %s (%s):\w > " % (grass_version, location_name)
  643. exit_val = call([gfile("etc", "run"), os.getenv('SHELL')])
  644. def done_message():
  645. if batch_job and os.access(batch_job, os.X_OK):
  646. message("Batch job '%s' (defined in GRASS_BATCH_JOB variable) was executed." % batch_job)
  647. message("Goodbye from GRASS GIS")
  648. sys.exit(exit_val)
  649. else:
  650. message("Done.")
  651. message("")
  652. message("Goodbye from GRASS GIS")
  653. message("")
  654. def clean_temp():
  655. message("Cleaning up temporary files ...")
  656. nul = open(os.devnull, 'w')
  657. call([gfile("etc", "clean_temp")], stdout = nul, stderr = nul)
  658. nul.close()
  659. def get_username():
  660. global user
  661. if windows:
  662. user = os.getenv('USERNAME')
  663. if not user:
  664. user = "user_name"
  665. else:
  666. user = os.getenv('USER')
  667. if not user:
  668. user = os.getenv('LOGNAME')
  669. if not user:
  670. try:
  671. p = subprocess.Popen(['whoami'], stdout = subprocess.PIPE)
  672. s = p.stdout.read()
  673. p.wait()
  674. user = s.strip()
  675. except:
  676. pass
  677. if not user:
  678. user = "user_%d" % os.getuid()
  679. def parse_cmdline():
  680. global args, grass_gui, create_new
  681. args = []
  682. for i in sys.argv[1:]:
  683. # Check if the user asked for the version
  684. if i in ["-v","--version"]:
  685. message(readfile(gfile("etc", "license")))
  686. sys.exit()
  687. # Check if the user asked for help
  688. elif i in ["help","-h","-help","--help"]:
  689. help_message()
  690. sys.exit()
  691. # Check if the -text flag was given
  692. elif i == "-text":
  693. grass_gui = 'text'
  694. # Check if the -gui flag was given
  695. elif i == "-gui":
  696. grass_gui = default_gui
  697. # Check if the -wxpython flag was given
  698. elif i in ["-wxpython","-wx"]:
  699. grass_gui = 'wxpython'
  700. # Check if the user wants to create a new mapset
  701. elif i == "-c":
  702. create_new = True
  703. else:
  704. args.append(i)
  705. ### MAIN script starts here
  706. # Get the system name
  707. windows = sys.platform == 'win32'
  708. cygwin = "cygwin" in sys.platform
  709. macosx = "darwin" in sys.platform
  710. # Set GISBASE
  711. os.environ['GISBASE'] = gisbase
  712. # set HOME
  713. if windows and not os.getenv('HOME'):
  714. os.environ['HOME'] = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH'))
  715. # set SHELL
  716. if windows and not os.getenv('SHELL'):
  717. os.environ['SHELL'] = os.getenv('COMSPEC', 'cmd.exe')
  718. grass_config_dir = os.path.join(os.getenv('HOME'), grass_config_dirname)
  719. atexit.register(cleanup)
  720. # Set default GUI
  721. default_gui = "wxpython"
  722. # the following is only meant to be an internal variable for debugging this script.
  723. # use 'g.gisenv set="DEBUG=[0-5]"' to turn GRASS debug mode on properly.
  724. grass_debug = os.getenv('GRASS_DEBUG')
  725. # GRASS_SH is normally just for Windows when not started from a bourne
  726. # shell. But when starting from Init.sh is still needed for GRASS_GUI (still true for GRASS 7?)
  727. os.environ['GRASS_SH'] = "/bin/sh"
  728. # Set GRASS version number for R interface etc (must be an env_var for MS-Windows)
  729. os.environ['GRASS_VERSION'] = grass_version
  730. # Set the GIS_LOCK variable to current process id
  731. gis_lock = str(os.getpid())
  732. os.environ['GIS_LOCK'] = gis_lock
  733. # Set the global grassrc file
  734. batch_job = os.getenv('GRASS_BATCH_JOB')
  735. if batch_job:
  736. gisrcrc = os.path.join(grass_config_dir, "rc.%s" % os.uname()[1])
  737. if not os.access(gisrcrc, os.R_OK):
  738. gisrcrc = os.path.join(grass_config_dir, "rc")
  739. else:
  740. gisrcrc = os.path.join(grass_config_dir, "rc")
  741. # Set the username and working directory
  742. get_username()
  743. # Parse the command-line options
  744. parse_cmdline()
  745. # Create the temporary directory and session grassrc file
  746. create_tmp()
  747. # Create the session grassrc file
  748. create_gisrc()
  749. # Ensure GRASS_GUI is set
  750. read_gui()
  751. # Get Locale name
  752. get_locale()
  753. # Set PATH, PYTHONPATH
  754. set_paths()
  755. # Set LD_LIBRARY_PATH (etc) to find GRASS shared libraries
  756. path_prepend(gfile("lib"), ld_library_path_var)
  757. # Set GRASS_PAGER, GRASS_WISH, GRASS_PYTHON, GRASS_GNUPLOT, GRASS_PROJSHARE
  758. set_defaults()
  759. # Set GRASS_HTML_BROWSER
  760. set_browser()
  761. #predefine monitor size for certain architectures
  762. if os.getenv('HOSTTYPE') == 'arm':
  763. #small monitor on ARM (iPAQ, zaurus... etc)
  764. os.environ['GRASS_HEIGHT'] = "320"
  765. os.environ['GRASS_WIDTH'] = "240"
  766. # First time user - GISRC is defined in the GRASS script
  767. if not os.access(gisrc, os.F_OK):
  768. grass_intro()
  769. else:
  770. clean_temp()
  771. message("Starting GRASS ...")
  772. # Check that the GUI works
  773. check_gui()
  774. # Parsing argument to get LOCATION
  775. if args == []:
  776. # Try interactive startup
  777. location = None
  778. else:
  779. non_interactive(args[0])
  780. # User selects LOCATION and MAPSET if not set
  781. set_data()
  782. # Set GISDBASE, LOCATION_NAME, MAPSET, LOCATION from $GISRC
  783. load_gisrc()
  784. # Check .gislock file
  785. check_lock()
  786. # build user fontcap if specified but not present
  787. make_fontcap()
  788. # predefine default driver if DB connection not defined
  789. # is this really needed?? Modules should call this when/if required.
  790. if not os.access(os.path.join(location, "VAR"), os.F_OK):
  791. call(['db.connect', '-c', '--quiet'])
  792. check_shell()
  793. check_batch_job()
  794. start_gui()
  795. clear_screen()
  796. # Display the version and license info
  797. if batch_job:
  798. say_hello()
  799. else:
  800. show_banner()
  801. say_hello()
  802. show_info()
  803. if sh in ['csh', 'tcsh']:
  804. csh_startup()
  805. elif sh in ['bash', 'msh', 'cygwin']:
  806. bash_startup()
  807. else:
  808. default_startup()
  809. clear_screen()
  810. clean_temp()
  811. try_remove(lockfile)
  812. # Save GISRC
  813. s = readfile(gisrc)
  814. if not os.path.exists(grass_config_dir):
  815. os.mkdir(grass_config_dir)
  816. writefile(gisrcrc, s)
  817. cleanup()
  818. #### after this point no more grass modules may be called ####
  819. done_message()