1
2
3 __doc__ = """GNUmed client launcher.
4
5 This is the launcher for the GNUmed GUI client. It takes
6 care of all the pre- and post-GUI runtime environment setup.
7
8 --quiet
9 Be extra quiet and show only _real_ errors in the log.
10 --debug
11 Pre-set the [debug mode] checkbox in the login dialog to
12 increase verbosity in the log file. Useful for, well, debugging :-)
13 --slave
14 Pre-set the [enable remote control] checkbox in the login
15 dialog to enable the XML-RPC remote control feature.
16 --hipaa
17 Enable HIPAA functionality which has user impact.
18 --profile=<file>
19 Activate profiling and write profile data to <file>.
20 --text-domain=<text domain>
21 Set this to change the name of the language file to be loaded.
22 Note, this does not change the directory the file is searched in,
23 only the name of the file where messages are loaded from. The
24 standard textdomain is, of course, "gnumed.mo".
25 --log-file=<file>
26 Use this to change the name of the log file.
27 See gmLog2.py to find out where the standard log file would
28 end up.
29 --conf-file=<file>
30 Use configuration file <file> instead of searching for it in
31 standard locations.
32 --lang-gettext=<language>
33 Explicitly set the language to use in gettext translation. The very
34 same effect can be achieved by setting the environment variable $LANG
35 from a launcher script.
36 --override-schema-check
37 Continue loading the client even if the database schema version
38 and the client software version cannot be verified to be compatible.
39 --skip-update-check
40 Skip checking for client updates. This is useful during development
41 and when the update check URL is unavailable (down).
42 --local-import
43 Adjust the PYTHONPATH such that GNUmed can be run from a local source tree.
44 --ui=<ui type>
45 Start an alternative UI. Defaults to wxPython if not specified.
46 Valid values: web (CherryPy), wxp (wxPython)
47 --version, -V
48 Show version information.
49 --help, -h, or -?
50 Show this help.
51 """
52
53 __version__ = "$Revision: 1.169 $"
54 __author__ = "H. Herb <hherb@gnumed.net>, K. Hilbert <Karsten.Hilbert@gmx.net>, I. Haywood <i.haywood@ugrad.unimelb.edu.au>"
55 __license__ = "GPL (details at http://www.gnu.org)"
56
57
58 import sys, os, os.path, signal, logging, platform
59
60
61
62 if __name__ != "__main__":
63 print "GNUmed startup: This is not intended to be imported as a module !"
64 print "-----------------------------------------------------------------"
65 print __doc__
66 sys.exit(1)
67
68
69
70 if os.name in ['posix'] and os.geteuid() == 0:
71 print """
72 GNUmed startup: GNUmed should not be run as root.
73 -------------------------------------------------
74
75 Running GNUmed as <root> can potentially put all
76 your medical data at risk. It is strongly advised
77 against. Please run GNUmed as a non-root user.
78 """
79 sys.exit(1)
80
81
82
83 current_client_version = u'GIT HEAD'
84
85 current_client_branch = u'GIT tree'
86
87 _log = None
88 _cfg = None
89 _old_sig_term = None
90 _known_short_options = u'h?V'
91 _known_long_options = [
92 u'debug',
93 u'slave',
94 u'skip-update-check',
95 u'profile=',
96 u'text-domain=',
97 u'log-file=',
98 u'conf-file=',
99 u'lang-gettext=',
100 u'ui=',
101 u'override-schema-check',
102 u'local-import',
103 u'help',
104 u'version',
105 u'hipaa'
106 ]
107
108 _known_ui_types = [
109 u'web',
110 u'wxp'
111 ]
112
113 import_error_sermon = """
114 GNUmed startup: Cannot load GNUmed Python modules !
115 ---------------------------------------------------
116 CRITICAL ERROR: Program halted.
117
118 Please make sure you have:
119
120 1) the required third-party Python modules installed
121 2) the GNUmed Python modules linked or installed into site-packages/
122 (if you do not run from a CVS tree the installer should have taken care of that)
123 3) your PYTHONPATH environment variable set up correctly
124
125 sys.path is currently set to:
126
127 %s
128
129 If you are running from a copy of the CVS tree make sure you
130 did run gnumed/check-prerequisites.sh with good results.
131
132 If you still encounter errors after checking the above
133 requirements please ask on the mailing list.
134 """
135
136
137 missing_cli_config_file = u"""
138 GNUmed startup: Missing configuration file.
139 -------------------------------------------
140
141 You explicitly specified a configuration file
142 on the command line:
143
144 --conf-file=%s
145
146 The file does not exist, however.
147 """
148
149
150 no_config_files = u"""
151 GNUmed startup: Missing configuration files.
152 --------------------------------------------
153
154 None of the below candidate configuration
155 files could be found:
156
157 %s
158
159 Cannot run GNUmed without any of them.
160 """
161
162
163
165
166 if not u'--local-import' in sys.argv:
167 return
168
169 print "GNUmed startup: Running from local source tree."
170 print "-----------------------------------------------"
171
172 local_python_base_dir = os.path.dirname (
173 os.path.abspath(os.path.join(sys.argv[0], '..'))
174 )
175
176
177
178 link_name = os.path.join(local_python_base_dir, 'Gnumed')
179 if not os.path.exists(link_name):
180 real_dir = os.path.join(local_python_base_dir, 'client')
181 print "Creating module import symlink ..."
182 print ' real dir:', real_dir
183 print ' link:', link_name
184 os.symlink(real_dir, link_name)
185
186 print "Adjusting PYTHONPATH ..."
187 sys.path.insert(0, local_python_base_dir)
188
200
211
216
218 from Gnumed.pycommon import gmCfg2
219
220 global _cfg
221 _cfg = gmCfg2.gmCfgData()
222 _cfg.add_cli (
223 short_options = _known_short_options,
224 long_options = _known_long_options
225 )
226
227 val = _cfg.get(option = '--debug', source_order = [('cli', 'return')])
228 if val is None:
229 val = False
230 _cfg.set_option (
231 option = u'debug',
232 value = val
233 )
234
235 val = _cfg.get(option = '--slave', source_order = [('cli', 'return')])
236 if val is None:
237 val = False
238 _cfg.set_option (
239 option = u'slave',
240 value = val
241 )
242
243 val = _cfg.get(option = '--skip-update-check', source_order = [('cli', 'return')])
244 if val is None:
245 val = False
246 _cfg.set_option (
247 option = u'skip-update-check',
248 value = val
249 )
250
251 val = _cfg.get(option = '--hipaa', source_order = [('cli', 'return')])
252 if val is None:
253 val = False
254 _cfg.set_option (
255 option = u'hipaa',
256 value = val
257 )
258
259 val = _cfg.get(option = '--local-import', source_order = [('cli', 'return')])
260 if val is None:
261 val = False
262 _cfg.set_option (
263 option = u'local-import',
264 value = val
265 )
266
267 _cfg.set_option (
268 option = u'client_version',
269 value = current_client_version
270 )
271
272 _cfg.set_option (
273 option = u'client_branch',
274 value = current_client_branch
275 )
276
277
279 _log.critical('SIGTERM (SIG%s) received, shutting down ...' % signum)
280 gmLog2.flush()
281 print 'GNUmed: SIGTERM (SIG%s) received, shutting down ...' % signum
282 if frame is not None:
283 print '%s::%s@%s' % (frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno)
284
285
286
287 if _old_sig_term in [None, signal.SIG_IGN]:
288 sys.exit(signal.SIGTERM)
289 else:
290 _old_sig_term(signum, frame)
291
295
306
308 src = [(u'cli', u'return')]
309
310 help_requested = (
311 _cfg.get(option = u'--help', source_order = src) or
312 _cfg.get(option = u'-h', source_order = src) or
313 _cfg.get(option = u'-?', source_order = src)
314 )
315
316 if help_requested:
317 print _(
318 'Help requested\n'
319 '--------------'
320 )
321 print __doc__
322 sys.exit(0)
323
342
343
345 """Create needed paths in user home directory."""
346
347 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'scripts')))
348 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'spellcheck')))
349 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'tmp')))
350 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'docs')))
351 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'xDT')))
352 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'EMR')))
353 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'xDT')))
354 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'logs')))
355
356 paths = gmTools.gmPaths(app_name = u'gnumed')
357
358 open(os.path.expanduser(os.path.join('~', '.gnumed', 'gnumed.conf')), 'a+').close()
359
362
364 """Detect and setup access to GNUmed config file.
365
366 Parts of this will have limited value due to
367 wxPython not yet being available.
368 """
369
370 enc = gmI18N.get_encoding()
371 paths = gmTools.gmPaths(app_name = u'gnumed')
372
373 candidates = [
374
375 [u'workbase', os.path.join(paths.working_dir, 'gnumed.conf')],
376
377 [u'system', os.path.join(paths.system_config_dir, 'gnumed-client.conf')],
378
379 [u'user', os.path.join(paths.user_config_dir, 'gnumed.conf')],
380
381 [u'local', os.path.join(paths.local_base_dir, 'gnumed.conf')]
382 ]
383
384 explicit_fname = _cfg.get(option = u'--conf-file', source_order = [(u'cli', u'return')])
385 if explicit_fname is None:
386 candidates.append([u'explicit', None])
387 else:
388 candidates.append([u'explicit', explicit_fname])
389
390 for candidate in candidates:
391 _cfg.add_file_source (
392 source = candidate[0],
393 file = candidate[1],
394 encoding = enc
395 )
396
397
398 if explicit_fname is not None:
399 if _cfg.source_files['explicit'] is None:
400 _log.error('--conf-file argument does not exist')
401 sys.exit(missing_cli_config_file % explicit_fname)
402
403
404 found_any_file = False
405 for f in _cfg.source_files.values():
406 if f is not None:
407 found_any_file = True
408 break
409 if not found_any_file:
410 _log.error('no config file found at all')
411 sys.exit(no_config_files % '\n '.join(candidates))
412
413
414 fname = u'mime_type2file_extension.conf'
415 _cfg.add_file_source (
416 source = u'user-mime',
417 file = os.path.join(paths.user_config_dir, fname),
418 encoding = enc
419 )
420 _cfg.add_file_source (
421 source = u'system-mime',
422 file = os.path.join(paths.system_config_dir, fname),
423 encoding = enc
424 )
425
427 global ui_type
428
429 ui_type = _cfg.get(option = u'--ui', source_order = [(u'cli', u'return')])
430
431 if ui_type in [True, False, None]:
432 ui_type = 'wxp'
433
434 ui_type = ui_type.strip()
435
436 if ui_type not in _known_ui_types:
437 _log.error('unknown UI type: %s', ui_type)
438 _log.debug('known UI types: %s', str(_known_ui_types))
439 print "GNUmed startup: Unknown UI type (%s). Defaulting to wxPython client." % ui_type
440 ui_type = 'wxp'
441
442 _log.debug('UI type: %s', ui_type)
443
445 _log.info('client expects database version [%s]', gmPG2.map_client_branch2required_db_version[current_client_branch])
446
447
448 timezone = _cfg.get (
449 group = u'backend',
450 option = 'client timezone',
451 source_order = [
452 ('explicit', 'return'),
453 ('workbase', 'return'),
454 ('local', 'return'),
455 ('user', 'return'),
456 ('system', 'return')
457 ]
458 )
459 if timezone is not None:
460 gmPG2.set_default_client_timezone(timezone)
461
464
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491 logging.raiseExceptions = False
492
493
494
495
496 setup_python_path()
497 setup_logging()
498 log_startup_info()
499 setup_console_exception_handler()
500 setup_cli()
501 setup_signal_handlers()
502
503 from Gnumed.pycommon import gmI18N, gmTools, gmDateTime, gmHooks
504 setup_locale()
505 handle_help_request()
506 handle_version_request()
507 setup_paths_and_files()
508 setup_date_time()
509 setup_cfg()
510 setup_ui_type()
511
512 from Gnumed.pycommon import gmPG2
513 setup_backend()
514
515
516 gmHooks.run_hook_script(hook = u'startup-before-GUI')
517
518 if ui_type == u'wxp':
519 from Gnumed.wxpython import gmGuiMain
520 profile_file = _cfg.get(option = u'--profile', source_order = [(u'cli', u'return')])
521 if profile_file is not None:
522 _log.info('writing profiling data into %s', profile_file)
523 import profile
524 profile.run('gmGuiMain.main()', profile_file)
525 else:
526 gmGuiMain.main()
527 elif ui_type == u'web':
528 from Gnumed.CherryPy import gmGuiWeb
529 gmGuiWeb.main()
530
531 gmHooks.run_hook_script(hook = u'shutdown-post-GUI')
532
533
534 shutdown_backend()
535 _log.info('Normally shutting down as main module.')
536 shutdown_logging()
537
538
539