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: chweb (CherryPy), wxp (wxPython), web (ProxiedWeb)
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 v2 or later (details at http://www.gnu.org)"
56
57
58 import sys
59 import os
60 import platform
61 import logging
62 import signal
63 import os.path
64 import shutil
65
66
67
68 if __name__ != "__main__":
69 print "GNUmed startup: This is not intended to be imported as a module !"
70 print "-----------------------------------------------------------------"
71 print __doc__
72 sys.exit(1)
73
74
75
76 if os.name in ['posix'] and os.geteuid() == 0:
77 print """
78 GNUmed startup: GNUmed should not be run as root.
79 -------------------------------------------------
80
81 Running GNUmed as <root> can potentially put all
82 your medical data at risk. It is strongly advised
83 against. Please run GNUmed as a non-root user.
84 """
85 sys.exit(1)
86
87
88
89 current_client_version = u'GIT HEAD'
90
91 current_client_branch = u'GIT tree'
92
93 _log = None
94 _cfg = None
95 _old_sig_term = None
96 _known_short_options = u'h?V'
97 _known_long_options = [
98 u'debug',
99 u'slave',
100 u'skip-update-check',
101 u'profile=',
102 u'text-domain=',
103 u'log-file=',
104 u'conf-file=',
105 u'lang-gettext=',
106 u'ui=',
107 u'override-schema-check',
108 u'local-import',
109 u'help',
110 u'version',
111 u'hipaa'
112 ]
113
114 _known_ui_types = [
115 u'web',
116 u'wxp',
117 u'chweb'
118 ]
119
120 import_error_sermon = """
121 GNUmed startup: Cannot load GNUmed Python modules !
122 ---------------------------------------------------
123 CRITICAL ERROR: Program halted.
124
125 Please make sure you have:
126
127 1) the required third-party Python modules installed
128 2) the GNUmed Python modules linked or installed into site-packages/
129 (if you do not run from a CVS tree the installer should have taken care of that)
130 3) your PYTHONPATH environment variable set up correctly
131
132 sys.path is currently set to:
133
134 %s
135
136 If you are running from a copy of the CVS tree make sure you
137 did run gnumed/check-prerequisites.sh with good results.
138
139 If you still encounter errors after checking the above
140 requirements please ask on the mailing list.
141 """
142
143
144 missing_cli_config_file = u"""
145 GNUmed startup: Missing configuration file.
146 -------------------------------------------
147
148 You explicitly specified a configuration file
149 on the command line:
150
151 --conf-file=%s
152
153 The file does not exist, however.
154 """
155
156
157 no_config_files = u"""
158 GNUmed startup: Missing configuration files.
159 --------------------------------------------
160
161 None of the below candidate configuration
162 files could be found:
163
164 %s
165
166 Cannot run GNUmed without any of them.
167 """
168
169
170
172
173 if not u'--local-import' in sys.argv:
174 return
175
176 print "GNUmed startup: Running from local source tree."
177 print "-----------------------------------------------"
178
179 local_python_base_dir = os.path.dirname (
180 os.path.abspath(os.path.join(sys.argv[0], '..'))
181 )
182
183
184
185 link_name = os.path.join(local_python_base_dir, 'Gnumed')
186 if not os.path.exists(link_name):
187 real_dir = os.path.join(local_python_base_dir, 'client')
188 print "Creating module import symlink ..."
189 print ' real dir:', real_dir
190 print ' link:', link_name
191 os.symlink(real_dir, link_name)
192
193 print "Adjusting PYTHONPATH ..."
194 sys.path.insert(0, local_python_base_dir)
195
207
218
223
225 from Gnumed.pycommon import gmCfg2
226
227 global _cfg
228 _cfg = gmCfg2.gmCfgData()
229 _cfg.add_cli (
230 short_options = _known_short_options,
231 long_options = _known_long_options
232 )
233
234 val = _cfg.get(option = '--debug', source_order = [('cli', 'return')])
235 if val is None:
236 val = False
237 _cfg.set_option (
238 option = u'debug',
239 value = val
240 )
241
242 val = _cfg.get(option = '--slave', source_order = [('cli', 'return')])
243 if val is None:
244 val = False
245 _cfg.set_option (
246 option = u'slave',
247 value = val
248 )
249
250 val = _cfg.get(option = '--skip-update-check', source_order = [('cli', 'return')])
251 if val is None:
252 val = False
253 _cfg.set_option (
254 option = u'skip-update-check',
255 value = val
256 )
257
258 val = _cfg.get(option = '--hipaa', source_order = [('cli', 'return')])
259 if val is None:
260 val = False
261 _cfg.set_option (
262 option = u'hipaa',
263 value = val
264 )
265
266 val = _cfg.get(option = '--local-import', source_order = [('cli', 'return')])
267 if val is None:
268 val = False
269 _cfg.set_option (
270 option = u'local-import',
271 value = val
272 )
273
274 _cfg.set_option (
275 option = u'client_version',
276 value = current_client_version
277 )
278
279 _cfg.set_option (
280 option = u'client_branch',
281 value = current_client_branch
282 )
283
284
286 _log.critical('SIGTERM (SIG%s) received, shutting down ...' % signum)
287 gmLog2.flush()
288 print 'GNUmed: SIGTERM (SIG%s) received, shutting down ...' % signum
289 if frame is not None:
290 print '%s::%s@%s' % (frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno)
291
292
293
294 if _old_sig_term in [None, signal.SIG_IGN]:
295 sys.exit(signal.SIGTERM)
296 else:
297 _old_sig_term(signum, frame)
298
302
313
315 src = [(u'cli', u'return')]
316
317 help_requested = (
318 _cfg.get(option = u'--help', source_order = src) or
319 _cfg.get(option = u'-h', source_order = src) or
320 _cfg.get(option = u'-?', source_order = src)
321 )
322
323 if help_requested:
324 print _(
325 'Help requested\n'
326 '--------------'
327 )
328 print __doc__
329 sys.exit(0)
330
349
350
352 """Create needed paths in user home directory."""
353
354 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'scripts')))
355 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'spellcheck')))
356 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'tmp')))
357 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'docs')))
358 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'xDT')))
359 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'EMR')))
360 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'xDT')))
361 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'logs')))
362
363 paths = gmTools.gmPaths(app_name = u'gnumed')
364
365 open(os.path.expanduser(os.path.join('~', '.gnumed', 'gnumed.conf')), 'a+').close()
366
369
371 """Detect and setup access to GNUmed config file.
372
373 Parts of this will have limited value due to
374 wxPython not yet being available.
375 """
376
377 enc = gmI18N.get_encoding()
378 paths = gmTools.gmPaths(app_name = u'gnumed')
379
380 candidates = [
381
382 [u'workbase', os.path.join(paths.working_dir, 'gnumed.conf')],
383
384 [u'system', os.path.join(paths.system_config_dir, 'gnumed-client.conf')],
385
386 [u'user', os.path.join(paths.user_config_dir, 'gnumed.conf')],
387
388 [u'local', os.path.join(paths.local_base_dir, 'gnumed.conf')]
389 ]
390
391 explicit_fname = _cfg.get(option = u'--conf-file', source_order = [(u'cli', u'return')])
392 if explicit_fname is None:
393 candidates.append([u'explicit', None])
394 else:
395 candidates.append([u'explicit', explicit_fname])
396
397 for candidate in candidates:
398 _cfg.add_file_source (
399 source = candidate[0],
400 file = candidate[1],
401 encoding = enc
402 )
403
404
405 if explicit_fname is not None:
406 if _cfg.source_files['explicit'] is None:
407 _log.error('--conf-file argument does not exist')
408 sys.exit(missing_cli_config_file % explicit_fname)
409
410
411 found_any_file = False
412 for f in _cfg.source_files.values():
413 if f is not None:
414 found_any_file = True
415 break
416 if not found_any_file:
417 _log.error('no config file found at all')
418 sys.exit(no_config_files % '\n '.join(candidates))
419
420
421 fname = u'mime_type2file_extension.conf'
422 _cfg.add_file_source (
423 source = u'user-mime',
424 file = os.path.join(paths.user_config_dir, fname),
425 encoding = enc
426 )
427 _cfg.add_file_source (
428 source = u'system-mime',
429 file = os.path.join(paths.system_config_dir, fname),
430 encoding = enc
431 )
432
434 global ui_type
435
436 ui_type = _cfg.get(option = u'--ui', source_order = [(u'cli', u'return')])
437
438 if ui_type in [True, False, None]:
439 ui_type = 'wxp'
440
441 ui_type = ui_type.strip()
442
443 if ui_type not in _known_ui_types:
444 _log.error('unknown UI type: %s', ui_type)
445 _log.debug('known UI types: %s', str(_known_ui_types))
446 print "GNUmed startup: Unknown UI type (%s). Defaulting to wxPython client." % ui_type
447 ui_type = 'wxp'
448
449 _log.debug('UI type: %s', ui_type)
450
452
453 db_version = gmPG2.map_client_branch2required_db_version[current_client_branch]
454 _log.info('client expects database version [%s]', db_version)
455 _cfg.set_option (
456 option = u'database_version',
457 value = db_version
458 )
459
460
461 timezone = _cfg.get (
462 group = u'backend',
463 option = 'client timezone',
464 source_order = [
465 ('explicit', 'return'),
466 ('workbase', 'return'),
467 ('local', 'return'),
468 ('user', 'return'),
469 ('system', 'return')
470 ]
471 )
472 if timezone is not None:
473 gmPG2.set_default_client_timezone(timezone)
474
477
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504 logging.raiseExceptions = False
505
516
517
518
519 setup_python_path()
520 setup_logging()
521 log_startup_info()
522 setup_console_exception_handler()
523 setup_cli()
524 setup_signal_handlers()
525
526 from Gnumed.pycommon import gmI18N, gmTools, gmDateTime, gmHooks
527 setup_locale()
528 handle_help_request()
529 handle_version_request()
530 setup_paths_and_files()
531 setup_date_time()
532 setup_cfg()
533 setup_ui_type()
534
535 from Gnumed.pycommon import gmPG2
536 if ui_type in [u'web']:
537 gmPG2.auto_request_login_params = False
538 setup_backend()
539
540
541 gmHooks.run_hook_script(hook = u'startup-before-GUI')
542
543 if ui_type == u'wxp':
544 from Gnumed.wxpython import gmGuiMain
545 profile_file = _cfg.get(option = u'--profile', source_order = [(u'cli', u'return')])
546 if profile_file is not None:
547 _log.info('writing profiling data into %s', profile_file)
548 import profile
549 profile.run('gmGuiMain.main()', profile_file)
550 else:
551 gmGuiMain.main()
552 elif ui_type == u'web':
553 from Gnumed.proxiedpyjamas import gmWebGuiServer
554 gmWebGuiServer.main()
555
556 elif ui_type == u'chweb':
557 from Gnumed.CherryPy import gmGuiWeb
558 gmGuiWeb.main()
559
560 gmHooks.run_hook_script(hook = u'shutdown-post-GUI')
561
562 shutdown_backend()
563 shutdown_tmp_dir()
564 _log.info('Normally shutting down as main module.')
565 shutdown_logging()
566
567
568