File: init.tcl.in

package info (click to toggle)
modules 5.6.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,996 kB
  • sloc: exp: 79,667; sh: 6,142; tcl: 5,895; makefile: 1,478; ansic: 474; python: 272; csh: 202; perl: 47; ruby: 44; lisp: 13
file content (889 lines) | stat: -rw-r--r-- 31,640 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
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
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
##########################################################################

# INIT.TCL, configuration and state handing procedures
# Copyright (C) 2002-2004 Mark Lakata
# Copyright (C) 2004-2017 Kent Mein
# Copyright (C) 2016-2025 Xavier Delaruelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

##########################################################################

# Runtime state properties (default value, proc to call to initialize state
# value?)
##nagelfar ignore +38 Found constant
array set g_state_defs [list\
   autoinit {0}\
   cache_mcookie_version {5.3}\
   clock_seconds {<undef> initStateClockSeconds}\
   domainname {<undef> {runCommand domainname}}\
   error_count {0}\
   extra_siteconfig_loaded {0}\
   false_rendered {0}\
   force {0}\
   hiding_threshold {0 initStateHidingThreshold}\
   inhibit_errreport {0}\
   inhibit_interp {0}\
   init_error_report {0}\
   is_stderr_tty {<undef> initStateIsStderrTty}\
   is_win {<undef> initStateIsWin}\
   kernelversion {<undef> {runCommand uname -v}}\
   lm_info_cached {0}\
   logfd {{} initStateLogfd}\
   logging {<undef> initStateLogging}\
   lsb_codename {<undef> {runCommand lsb_release -s -c}}\
   lsb_id {<undef> {runCommand lsb_release -s -i}}\
   lsb_release {<undef> {runCommand lsb_release -s -r}}\
   machine [list $::tcl_platform(machine)]\
   modules_release {@MODULES_RELEASE@}\
   nodename {<undef> {runCommand uname -n}}\
   os [list $::tcl_platform(os)]\
   osversion [list $::tcl_platform(osVersion)]\
   paginate {<undef> initStatePaginate}\
   path_separator {<undef> initStatePathSeparator}\
   report_format {regular}\
   reportfd {stderr initStateReportfd}\
   return_false {0}\
   siteconfig_loaded {0}\
   shelltype {<undef> initStateShellType}\
   sub1_separator {&}\
   sub2_separator {|}\
   tcl_ext_lib_loaded {0}\
   tcl_version [list [info patchlevel]]\
   term_columns {<undef> initStateTermColumns}\
   timer {0}\
   usergroups {<undef> initStateUsergroups}\
   username {<undef> initStateUsername}\
]

# Configuration option properties (superseding environment variable, default
# value, is configuration lockable to default value, value kind, valid value
# list?, internal value representation?, proc to call to initialize option
# value, valid value list kind
##nagelfar ignore #81 Too long line
array set g_config_defs [list\
   contact {MODULECONTACT root@localhost 0 s}\
   abort_on_error {MODULES_ABORT_ON_ERROR {@abortonerror@} 0 l {load ml\
      mod-to-sh purge reload switch switch_unload try-load unload} {} {}\
      eltlist}\
   auto_handling {MODULES_AUTO_HANDLING @autohandling@ 0 b {0 1}}\
   avail_indepth {MODULES_AVAIL_INDEPTH @availindepth@ 0 b {0 1}}\
   avail_output {MODULES_AVAIL_OUTPUT {@availoutput@} 0 l {modulepath alias\
      provided-alias dirwsym indesym sym tag key hidden variant variantifspec\
      via} {} {} eltlist}\
   avail_terse_output {MODULES_AVAIL_TERSE_OUTPUT {@availterseoutput@} 0 l\
      {modulepath alias provided-alias dirwsym indesym sym tag key hidden\
      variant variantifspec} {} {} eltlist}\
   cache_buffer_bytes {MODULES_CACHE_BUFFER_BYTES 32768 0 i {4096 1000000} {}\
      {} intbe}\
   cache_expiry_secs {MODULES_CACHE_EXPIRY_SECS 0 0 i {0 31536000} {} {}\
      intbe}\
   collection_pin_version {MODULES_COLLECTION_PIN_VERSION 0 0 b {0 1}}\
   collection_pin_tag {MODULES_COLLECTION_PIN_TAG 0 0 b {0 1}}\
   collection_target {MODULES_COLLECTION_TARGET <undef> 0 s}\
   color {MODULES_COLOR @color@ 0 s {never auto always} {0 1 2}\
      initConfColor}\
   colors {MODULES_COLORS {} 0 l {} {} initConfColors}\
   conflict_unload {MODULES_CONFLICT_UNLOAD @conflictunload@ 0 b {0 1}}\
   csh_limit {{} 4000 0 i}\
   extra_siteconfig {MODULES_SITECONFIG <undef> 1 s {}}\
   editor {MODULES_EDITOR {@editor@} 0 s {} {} initConfEditor}\
   hide_auto_loaded {MODULES_HIDE_AUTO_LOADED 0 0 b {0 1}}\
   home {MODULESHOME {@moduleshome@} 0 s}\
   icase {MODULES_ICASE @icase@ 0 s {never search always}}\
   ignore_cache {MODULES_IGNORE_CACHE 0 0 b {0 1}}\
   ignore_user_rc {MODULES_IGNORE_USER_RC 0 0 b {0 1}}\
   ignored_dirs {{} {CVS RCS SCCS .svn .git .SYNC .sos} 0 o}\
   implicit_requirement {MODULES_IMPLICIT_REQUIREMENT @implicitrequirement@ 0\
      b {0 1}}\
   list_output {MODULES_LIST_OUTPUT {@listoutput@} 0 l {header idx variant\
      alias indesym sym tag hidden key} {} {} eltlist}\
   list_terse_output {MODULES_LIST_TERSE_OUTPUT {@listterseoutput@} 0 l\
      {header idx variant alias indesym sym tag hidden key} {} {} eltlist}\
   locked_configs {{} {@lockedconfigs@} 0 o}\
   logged_events {MODULES_LOGGED_EVENTS {@loggedevents@} 1 l {auto_eval\
      requested_eval requested_cmd} {} {} eltlist}\
   logger {MODULES_LOGGER {@loggercmd@} 1 s}\
   mcookie_check {MODULES_MCOOKIE_CHECK always 0 s {eval always}}\
   mcookie_version_check {MODULES_MCOOKIE_VERSION_CHECK\
      @mcookieversioncheck@ 0 b {0 1}}\
   ml {MODULES_ML @ml@ 0 b {0 1}}\
   nearly_forbidden_days {MODULES_NEARLY_FORBIDDEN_DAYS @nearlyforbiddendays@\
      0 i {0 365} {} {} intbe}\
   pager {MODULES_PAGER {@pagercmd@} 0 s}\
   protected_envvars {MODULES_PROTECTED_ENVVARS <undef> 0 l}\
   rcfile {MODULERCFILE <undef> 0 l}\
   redirect_output {MODULES_REDIRECT_OUTPUT 1 0 b {0 1}}\
   require_via {MODULES_REQUIRE_VIA @requirevia@ 0 b {0 1}}\
   reset_target_state {MODULES_RESET_TARGET_STATE __init__ 0 s}\
   quarantine_support {MODULES_QUARANTINE_SUPPORT @quarantinesupport@ 0 b {0\
      1}}\
   run_quarantine {MODULES_RUN_QUARANTINE <undef> 0 o}\
   shells_with_ksh_fpath {MODULES_SHELLS_WITH_KSH_FPATH {} 0 l {sh bash csh\
      tcsh fish} {} {} eltlist}\
   silent_shell_debug {MODULES_SILENT_SHELL_DEBUG @silentshdbgsupport@ 0 b {0\
      1}}\
   siteconfig {{} {@etcdir@/siteconfig.tcl} 0 s}\
   spider_indepth {MODULES_SPIDER_INDEPTH @spiderindepth@ 0 b {0 1}}\
   spider_output {MODULES_SPIDER_OUTPUT {@spideroutput@} 0 l {modulepath\
      alias provided-alias dirwsym indesym sym tag key hidden variant\
      variantifspec via} {} {} eltlist}\
   spider_terse_output {MODULES_SPIDER_TERSE_OUTPUT {@spiderterseoutput@} 0 l\
      {modulepath alias provided-alias dirwsym indesym sym tag key hidden\
      variant variantifspec} {} {} eltlist}\
   source_cache {MODULES_SOURCE_CACHE @sourcecache@ 0 b {0 1}}\
   sticky_purge {MODULES_STICKY_PURGE {@stickypurge@} 0 s {error warning\
      silent}}\
   tag_abbrev {MODULES_TAG_ABBREV {@tagabbrev@} 0 l {} {} initConfTagAbbrev}\
   tag_color_name {MODULES_TAG_COLOR_NAME {@tagcolorname@} 0 l {} {}\
      initConfTagColorName}\
   tcl_ext_lib {{} {} 0 s {} {} initConfTclExtLib}\
   tcl_linter {MODULES_TCL_LINTER {@tcllintercmd@} 0 s}\
   term_background {MODULES_TERM_BACKGROUND @termbg@ 0 s {dark light}}\
   term_width {MODULES_TERM_WIDTH 0 0 i {0 1000} {} {} intbe}\
   unique_name_loaded {MODULES_UNIQUE_NAME_LOADED @uniquenameloaded@ 0 b {0\
      1}}\
   unload_match_order {MODULES_UNLOAD_MATCH_ORDER @unloadmatchorder@ 0 s\
      {returnlast returnfirst}}\
   implicit_default {MODULES_IMPLICIT_DEFAULT @implicitdefault@ 1 b {0 1}}\
   extended_default {MODULES_EXTENDED_DEFAULT @extendeddefault@ 0 b {0 1}}\
   advanced_version_spec {MODULES_ADVANCED_VERSION_SPEC @advversspec@ 0 b {0\
      1}}\
   search_match {MODULES_SEARCH_MATCH @searchmatch@ 0 s {starts_with\
      contains}}\
   set_shell_startup {MODULES_SET_SHELL_STARTUP @setshellstartup@ 0 b {0 1}}\
   variant_shortcut {MODULES_VARIANT_SHORTCUT {@variantshortcut@} 0 l {} {}\
      initConfVariantShortcut}\
   verbosity {MODULES_VERBOSITY @verbosity@ 0 s {silent concise normal\
      verbose verbose2 trace debug debug2}}\
   wa_277 {MODULES_WA_277 @wa277@ 0 b {0 1}}\
]

# Get state value
proc getState {state {valifundef {}} {catchinitproc 0}} {
   if {![info exists ::g_states($state)]} {
      # fetch state properties (including its default value) if defined
      if {[info exists ::g_state_defs($state)]} {
         lassign $::g_state_defs($state) value initproclist
      } else {
         set value <undef>
         set initproclist {}
      }

      # call specific proc to initialize state if any
      if {$initproclist ne {}} {
         # catch init procedure error and report it as warning, so default
         # value will get set for state
         if {$catchinitproc} {
            if {[catch {set value [{*}$initproclist]} errMsg]} {
               reportWarning $errMsg
            }
         } else {
            set value [{*}$initproclist]
         }
      # overridden value coming the command-line
      ##nagelfar ignore Suspicious variable
      } elseif {[info exists ::asked_$state]} {
         set value [set ::asked_$state]
      }

      # return passed value if undefined and no value record
      if {$value eq {<undef>}} {
         set value $valifundef
      } else {
         setState $state $value
      }
      return $value
   } else {
      return $::g_states($state)
   }
}

# Clear state
proc unsetState {state} {
   if {[isStateDefined $state]} {
      unset ::g_states($state)
      reportDebug "$state unset"
   }
}

# Set state value
proc setState {state value} {
   set ::g_states($state) $value
   reportDebug "$state set to '$value'"
}

# Append each passed value to the existing state value list
proc lappendState {state args} {
   if {$state eq {-nodup}} {
      set state [lindex $args 0]
      # retrieve current val through getState to initialize it if still undef
      set value [getState $state]
      ##nagelfar ignore Found constant
      appendNoDupToList value {*}[lrange $args 1 end]
      setState $state $value
   } else {
      lappend ::g_states($state) {*}$args
      reportDebug "$state appended with '$args'"
   }
}

# Remove last element from state value list
proc lpopState {state} {
   setState $state [lrange [getState $state] 0 end-1]
}

# Return first element from state value list
proc topState {state} {
   return [lindex [getState $state] 0]
}

# Return last element from state value list
proc currentState {state} {
   return [lindex [getState $state] end]
}

# Get number of element from state value list
proc depthState {state} {
   return [llength [getState $state]]
}

# Check if state has been defined
proc isStateDefined {state} {
   return [info exists ::g_states($state)]
}

# Check if state equals passed value
proc isStateEqual {state value} {
   return [expr {[getState $state] eq $value}]
}

proc isConfigLocked {option} {
   return [expr {[lsearch -exact [getConf locked_configs] $option] != -1}]
}

# Get configuration option value
proc getConf {option {valifundef {}}} {
   if {![info exists ::g_configs($option)]} {
      # fetch option properties (including its default value)
      lassign $::g_config_defs($option) envvar value islockable valuekind\
         validvallist intvallist initproc validvallistkind

      # ensure option is not locked before superseding its default value
      if {!$islockable || ![isConfigLocked $option]} {
         # call specific proc to initialize config option if any
         if {$initproc ne {}} {
            set value [$initproc $envvar $value $validvallist $intvallist]
         } else {
            # overridden value coming from environment
            if {$envvar ne {} && [isEnvVarDefined $envvar]} {
               switch -- $validvallistkind {
                  eltlist {
                     # ignore non-valid values
                     if {![isDiffBetweenList [split $::env($envvar) :]\
                        $validvallist]} {
                        set value $::env($envvar)
                     }
                  }
                  intbe {
                     # ignore non-valid values
                     if {[string is integer -strict $::env($envvar)] &&\
                        $::env($envvar) >= [lindex $validvallist 0] &&\
                        $::env($envvar) <= [lindex $validvallist 1]} {
                        set value $::env($envvar)
                     }
                  }
                  {} {
                     # ignore non-valid values
                     ##nagelfar ignore +3 Non static subcommand
                     if {[switch -- [llength $validvallist] {
                        0 {expr {1 == 1}}
                        1 {string is $validvallist -strict $::env($envvar)}
                        default {expr {$::env($envvar) in $validvallist}}
                     }]} {
                        set value $::env($envvar)
                     }
                  }
               }
            }

            # overridden value coming the command-line (already validated)
            ##nagelfar ignore Suspicious variable
            if {[info exists ::asked_$option]} {
               set askedval [set ::asked_$option]
               # append or subtract value to existing configuration value if
               # new value starts with '+' or '-' (for colon-separated list
               # option only)
               if {$valuekind eq {l} && [string index $askedval 0] in {+ -}} {
                  set curvaluelist [split $value :]
                  switch -- [string index $askedval 0] {
                     + {
                        ##nagelfar ignore Found constant
                        appendNoDupToList curvaluelist {*}[split [string\
                           range $askedval 1 end] :]
                     }
                     - {
                        lassign [getDiffBetweenList $curvaluelist [split\
                           [string range $askedval 1 end] :]] curvaluelist
                     }
                  }
                  set value [join $curvaluelist :]
               } else {
                  set value $askedval
               }
            }

            # convert value to its internal representation
            if {[llength $intvallist]} {
               set value [lindex $intvallist [lsearch -exact $validvallist\
                  $value]]
            }
         }
      }

      # return passed value if undefined and no value record
      if {$value eq {<undef>}} {
         set value $valifundef
      } else {
         setConf $option $value
      }
      return $value
   } else {
      return $::g_configs($option)
   }
}

# Set configuration option value
proc setConf {option value} {
   set ::g_configs($option) $value
   reportDebug "$option set to '$value'"
}

# Unset configuration option value if it is set
proc unsetConf {option} {
   if {[info exists ::g_configs($option)]} {
      unset ::g_configs($option)
      reportDebug "$option unset"
   }
}

# Append each passed value to the existing config option value list
proc lappendConf {option args} {
   # retrieve current value through getConf to initialize it if still undef
   set value [getConf $option]
   ##nagelfar ignore Found constant
   appendNoDupToList value {*}$args
   setConf $option $value
}

# Get configuration option value split as a list
proc getConfList {option {valifundef {}}} {
   return [split [getConf $option $valifundef] :]
}

# Source site config which can be used to define global procedures or
# settings. We first look for the global siteconfig, then if an extra
# siteconfig is defined and allowed, source that file if it exists
proc sourceSiteConfig {} {
   lappend siteconfiglist [getConf siteconfig]
   for {set i 0} {$i < [llength $siteconfiglist]} {incr i} {
      set siteconfig [lindex $siteconfiglist $i]
      if {[file readable $siteconfig]} {
         reportDebug "Source site configuration ($siteconfig)"
         if {[catch {uplevel 1 source "{$siteconfig}"} errMsg]} {
            set errMsg "Site configuration source failed\n"
            # issue line number is lost due to uplevel use
            append errMsg [formatErrStackTrace $::errorInfo $siteconfig {}]
            reportErrorAndExit $errMsg
         }
         ##nagelfar ignore Found constant
         if {$siteconfig eq [getConf siteconfig]} {
            setState siteconfig_loaded 1
         } else {
            setState extra_siteconfig_loaded 1
         }
      }
      # check on extra_siteconfig after initial siteconfig loaded in case
      # it inhibits this extra load
      ##nagelfar ignore Found constant
      if {$siteconfig eq [getConf siteconfig] && [getConf\
         extra_siteconfig] ne {}} {
         lappend siteconfiglist [getConf extra_siteconfig]
      }
   }
}

# Used to tell if a machine is running Windows or not
proc initStateIsWin {} {
   return [expr {$::tcl_platform(platform) eq {windows}}]
}

# Get default path separator
proc initStatePathSeparator {} {
   return [expr {[getState is_win] ? {;} : {:}}]
}

# Detect if terminal is attached to stderr message channel
proc initStateIsStderrTty {} {
   return [expr {![catch {fconfigure stderr -mode}]}]
}

# Determine if pagination need to be started
proc initStatePaginate {} {
   set pager [getConf pager]
   # empty or 'cat' pager command means no-pager
   set no_cmds [list {} cat]
   set only_shell_types [list sh csh fish cmd pwsh]
   # default pager enablement depends on pager command value and current shell
   set paginate [expr {[file tail [lindex $pager 0]] ni $no_cmds && [getState\
      shelltype] in $only_shell_types}]

   # asked enablement could only nullify a previous asked disablement as it
   # requires a valid pager command configuration, which by default enables
   # pagination; some module command may also turn off pager; also if error
   # stream is not attached to a terminal
   set no_subcmds [list clear edit]
   if {$paginate && (([info exists ::asked_paginate] && !$::asked_paginate)\
      || [getState subcmd] in $no_subcmds || ([getState subcmd] eq {ml} &&\
      [lindex [getState subcmd_args] 0] in $no_subcmds) || ![getState\
      is_stderr_tty])} {
      set paginate 0
   }

   return $paginate
}

# start pager pipe process with defined configuration
proc initStateReportfd {} {
   # get default value
   lassign $::g_state_defs(reportfd) reportfd

   # start pager at first call and only if enabled
   if {[getState paginate]} {
      if {[catch {
         set reportfd [open "|[getConf pager] >@stderr 2>@stderr" w]
         fconfigure $reportfd -buffering line -blocking 1 -buffersize 65536
      } errMsg]} {
         # silently set reportfd to its fallback value to process warn msg
         set ::g_states(reportfd) $reportfd
         reportWarning $errMsg
      }
   }

   # startup content in case of structured output format (puts here rather
   # calling report proc to avoid infinite reportfd init loop
   if {[isStateEqual report_format json]} {
      puts -nonewline $reportfd \{
   }

   return $reportfd
}

# Determine if logging need to be started
proc initStateLogging {} {
   set logger_not_empty [string length [lindex [getConf logger] 0]]
   set something_to_log [info exists ::g_log_msg_list]
   return [expr {$logger_not_empty && $something_to_log}]
}

# start logger pipe process with defined configuration
proc initStateLogfd {} {
   # sets default fallback value
   lassign $::g_state_defs(logfd) logfd

   # start logger at first call and only if enabled
   if {[getState logging]} {
      if {[catch {
         # drop output of logger command to avoid it pollutes main channels
         set logfd [open "|[getConf logger] >/dev/null 2>/dev/null" w]
         fconfigure $logfd -buffering none -blocking 1
      } errMsg]} {
         reportWarning $errMsg
      }
   }

   return $logfd
}

# Provide columns number for output formatting
proc initStateTermColumns {} {
   set cols [getConf term_width]
   if {$cols == 0} {
      # determine col number from tty capabilities
      # tty info query depends on running OS
      switch -- $::tcl_platform(os) {
         SunOS {
            catch {regexp {columns = (\d+);} [exec stty] match cols} errMsg
         }
         {Windows NT} {
            catch {regexp {Columns:\s+(\d+)} [exec mode] match cols} errMsg
         }
         default {
            catch {set cols [lindex [exec stty size] 1]} errMsg
         }
      }
      # default size if tty cols cannot be found
      set cols [expr {![info exists cols] || $cols eq {0} ? 80 : $cols}]
   }
   return $cols
}

# Deduce shelltype value from shell state value
proc initStateShellType {} {
   switch -- [getState shell] {
      sh - bash - ksh - zsh {
         return sh
      }
      csh - tcsh {
         return csh
      }
      default {
         return [getState shell]
      }
   }
}

proc initStateHidingThreshold {} {
   # sets default fallback value
   lassign $::g_state_defs(hiding_threshold) hiding_threshold

   if {[isEltInReport hidden 0]} {
      set hiding_threshold 2
   } elseif {[info exists ::asked_hiding_threshold]} {
      set hiding_threshold $::asked_hiding_threshold
   }

   return $hiding_threshold
}

# Get all groups of user running modulecmd.tcl process
proc __initStateUsergroups {} {
   # ensure groups including space in their name (found on Cygwin/MSYS
   # platforms) are correctly set as list element
   if {[catch {
      return [split [string range [runCommand id -G -n -z] 0 end-1] \0]
   } errMsg]} {
      # fallback if '-z' option is not supported
      return [runCommand id -G -n]
   }
}

# Get name of user running modulecmd.tcl process
proc __initStateUsername {} {
   return [runCommand id -u -n]
}

# Get Epoch time (number of seconds elapsed since Unix epoch)
proc __initStateClockSeconds {} {
   return [clock seconds]
}

# Initialize Select Graphic Rendition table
proc initConfColors {envvar value validvallist intvallist} {
   # overridden value coming from environment
   if {[isEnvVarDefined $envvar]} {
      set colors_list $::env($envvar)
      if {[catch {
         # test overridden value could be set to a dummy array variable
         array set test_colors [split $colors_list {:=}]
      } errMsg ]} {
         # report issue as a debug message rather warning to avoid
         # disturbing user with a warning message in the middle of a
         # useful output as this table will be initialized at first use
         reportDebug "Ignore invalid value set in $envvar ($colors_list)"
         unset colors_list
      }
   }

   # if no valid override set use default color theme for terminal
   # background color kind (light or dark)
   if {![info exists colors_list]} {
      if {[getConf term_background] eq {light}} {
         ##nagelfar ignore Too long line
         set colors_list {@lightbgcolors@}
      } else {
         ##nagelfar ignore Too long line
         set colors_list {@darkbgcolors@}
      }
      if {[catch {
         array set test_colors [split $colors_list {:=}]
      } errMsg ]} {
         reportDebug "Ignore invalid default [getConf term_background]\
            background colors ($colors_list)"
         # define an empty list if no valid value set
         set colors_list {}
      }
   }

   # check each color defined and unset invalid codes
   set value {}
   foreach {elt col} [split $colors_list {:=}] {
      if {![regexp {^[\d;]+$} $col]} {
         reportDebug "Ignore invalid color code for '$elt' ($col)"
      } else {
         lappend value $elt=$col
      }
   }
   set value [join $value :]

   # set SGR table as an array to easily access rendition for each key
   array unset ::g_colors
   array set ::g_colors [split $value {:=}]

   return $value
}

# Initialize color configuration value
proc initConfColor {envvar value validvallist intvallist} {
   # overridden value coming from environment via standard variable
   # https://no-color.org/ and https://bixense.com/clicolors/
   if {[isEnvVarDefined NO_COLOR]} {
      set value never
   } elseif {[isEnvVarDefined CLICOLOR]} {
      if {[envVarEquals CLICOLOR 0]} {
         set value never
      } else {
         set value auto
      }
   } elseif {[isEnvVarDefined CLICOLOR_FORCE] && $::env(CLICOLOR_FORCE) ne\
      {0}} {
      set value always
   }

   # overridden value coming from environment via Modules-specific variable
   if {$envvar ne {} && [isEnvVarDefined $envvar]} {
      # ignore non-valid values
      if {![llength $validvallist] || $::env($envvar) in $validvallist} {
         set value $::env($envvar)
      }
   }

   # overridden value coming the command-line
   if {[info exists ::asked_color]} {
      set value [set ::asked_color]
   }

   # convert value to its internal representation
   if {[llength $intvallist]} {
      set value [lindex $intvallist [lsearch -exact $validvallist $value]]
   }

   # disable color mode if no terminal attached except if 'always' asked
   if {$value != 0 && (![getState is_stderr_tty] || $value == 2)} {
      incr value -1
   }

   # initialize color theme if color mode enabled
   getConf colors

   return $value
}

# Initialize tcl_ext_lib configuration value
proc initConfTclExtLib {envvar value validvallist intvallist} {
   set libfile libtclenvmodules@SHLIB_SUFFIX@

   # determine lib directory
   ##nagelfar ignore #19 Strange command
   ##nagelfar ignore +13 Too long line
   @notmultilibsupport@set libdir {@libdir@}
   @multilibsupport@switch -- [getState machine] {
   @multilibsupport@   x86_64 - aarch64 - ppc64le - s390x {
   @multilibsupport@      set libdirmain {@libdir64@}
   @multilibsupport@      set libdiralt {@libdir32@}
   @multilibsupport@   }
   @multilibsupport@   default {
   @multilibsupport@      set libdirmain {@libdir32@}
   @multilibsupport@      set libdiralt {@libdir64@}
   @multilibsupport@   }
   @multilibsupport@}
   @multilibsupport@# use alternative arch lib if available and not main one
   @multilibsupport@if {![file exists [file join $libdirmain $libfile]] && [file exists [file\
   @multilibsupport@   join $libdiralt $libfile]]} {
   @multilibsupport@   set libdir $libdiralt
   @multilibsupport@} else {
   @multilibsupport@   set libdir $libdirmain
   @multilibsupport@}
   ##nagelfar variable libdir

   return [file join $libdir $libfile]
}

# Initialize module tag abbreviation table
proc initConfTagAbbrev {envvar value validvallist intvallist} {
   # overridden value coming from environment
   if {[isEnvVarDefined $envvar]} {
      if {[catch {
         # try to set the tag-abbreviation mapping table
         array set ::g_tagAbbrev [split $::env($envvar) {:=}]
         set value $::env($envvar)
      } errMsg ]} {
         reportWarning "Ignore invalid value set in $envvar ($::env($envvar))"
         array unset ::g_tagAbbrev
      }
   }

   # test default value
   if {![array exists ::g_tagAbbrev]} {
      if {[catch {
         array set ::g_tagAbbrev [split $value {:=}]
      } errMsg ]} {
         reportWarning "Ignore invalid default value for 'tag_abbrev' config\
            ($value)"
         array unset ::g_tagAbbrev
         # define an empty list if no valid value set
         set value {}
      }
   }

   # build abbrev:tagname array
   foreach {tag abbrev} [array get ::g_tagAbbrev] {
      # skip tags not relevant for current command, that share their
      # abbreviation with another tag
      switch -- $tag {
         hidden-loaded {
            set setabbrevtag [expr {[currentState commandname] eq {list}}]
         }
         hidden {
            set setabbrevtag [expr {[currentState commandname] in {avail\
               spider}}]
         }
         default {
            set setabbrevtag 1
         }
      }
      if {$setabbrevtag} {
         set ::g_abbrevTag($abbrev) $tag
      }
   }

   return $value
}

# Initialize module tag color name table
proc initConfTagColorName {envvar value validvallist intvallist} {
   # overridden value coming from environment
   if {[isEnvVarDefined $envvar]} {
      set value $::env($envvar)
   }

   # set table for efficient search
   foreach tag [split $value :] {
      set ::g_tagColorName($tag) 1
   }

   return $value
}

# Initialize interactive editor command
proc initConfEditor {envvar value validvallist intvallist} {
   # overridden value coming from environment via Modules-specific variable
   if {$envvar ne {} && [isEnvVarDefined $envvar]} {
      set value $::env($envvar)
   # overridden value coming from environment via standard variable
   } elseif {[isEnvVarDefined VISUAL]} {
      set value $::env(VISUAL)
   } elseif {[isEnvVarDefined EDITOR]} {
      set value $::env(EDITOR)
   }
   return $value
}

# Initialize variant shortcut table
proc initConfVariantShortcut {envvar value validvallist intvallist} {
   # overridden value coming from environment
   if {[isEnvVarDefined $envvar]} {
      if {[catch {
         # try to set the variant-shortcut mapping table
         array set testarr [split $::env($envvar) {:=}]
         set value $::env($envvar)
         set setfromenv 1
      } errMsg ]} {
         reportWarning "Ignore invalid value set in $envvar ($::env($envvar))"
      }
   }

   # test default value
   if {![info exists setfromenv]} {
      if {[catch {
         array set testarr [split $value {:=}]
      } errMsg ]} {
         reportWarning "Ignore invalid default value for 'variant_shortcut'\
            config ($value)"
         # define an empty list if no valid value set
         set value {}
      }
   }

   # ignore shortcut if not equal to one character or if set on alphanum char
   # or on char with special meaning
   foreach {vr sc} [split $value {:=}] {
      if {[string length $sc] == 1 && ![string match {[a-zA-Z0-9+~/@=-,:]}\
         $sc]} {
         # remove duplicate shortcut or variant definition
         if {[info exists ::g_variantShortcut($vr)]} {
            unset ::g_shortcutVariant($::g_variantShortcut($vr))
         }
         if {[info exists ::g_shortcutVariant($sc)]} {
            unset ::g_variantShortcut($::g_shortcutVariant($sc))
         }
         set ::g_variantShortcut($vr) $sc
         set ::g_shortcutVariant($sc) $vr
      }
   }

   # update value after above filtering step
   set value {}
   foreach vr [array names ::g_variantShortcut] {
      if {[string length $value]} {
         append value :
      }
      append value $vr=$::g_variantShortcut($vr)
   }

   return $value
}

# Is currently set verbosity level is equal or higher than level passed as arg
proc isVerbosityLevel {name} {
   return [expr {[lsearch -exact [lindex $::g_config_defs(verbosity) 4]\
      [getConf verbosity]] >= [lsearch -exact [lindex\
      $::g_config_defs(verbosity) 4] $name]}]
}

# Is match performed in a case sensitive or insensitive manner
proc isIcase {} {
   # depending on current sub-command, list values that equal to a case
   # insensitive match enablement
   lappend enabledValList always
   if {[currentState commandname] in [list avail list whatis search paths\
      savelist spider]} {
      lappend enabledValList search
   }
   return [expr {[getConf icase] in $enabledValList}]
}

proc commandAbortOnError {{command {}}} {
   if {![string length $command]} {
      set command [currentState commandname]
   }
   set abort_command_list [getConfList abort_on_error]
   return [expr {[isTopEvaluation] && ![getState force] && $command in\
      $abort_command_list}]
}

# ;;; Local Variables: ***
# ;;; mode:tcl ***
# ;;; End: ***
# vim:set tabstop=3 shiftwidth=3 expandtab autoindent: