This file is indexed.

/usr/lib/exmh/editor.tcl is in exmh 1:2.8.0-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
#
# editor.tcl --
#	Editor interactions
#
# Copyright (c) 1993 Xerox Corporation.
# Use and copying of this software and preparation of derivative works based
# upon this software are permitted. Any distribution of this software or
# derivative works must comply with all applicable United States export
# control laws. This software is made available AS IS, and Xerox Corporation
# makes no warranty about the software, its performance or its conformity to
# any specification.

# Message composing and editor interaction

proc Edit_Init {} {
    global mhProfile editor
    case $mhProfile(editor) {
	{*mxedit* sedit} {set prog $mhProfile(editor)}
	default {set prog sedit}
    }
    Preferences_Add "Editor Support" \
"Exmh has a built-in editor for composing messages, named \"sedit\".
It can also interface to other editors.  For non-TK editors like vi
or emacs, preface the editor command with \"exmh-async\" so the editor
runs as a detached process.  For TK-aware applications, suffix the
command with an & so your editor detaches into the background.  In
this case the first argument to the editor is the name of the exmh
interpreter, and the second argument is the draft file name.
If your editor knows how to post a message directly, preface
the command with \"give-away\".  The emacsclient and gnuclient
cases listed in the examples below are special cases of this.
If you want to pass a -geo argument to your program, you need to
wrap it up to prevent exmh-async from grabbing it.  See the last
example below.
Example commands include:
sedit
mxedit
emacsclient &
give-away emacsclient
gnuclient &
give-away gnuclient
exmh-async emacs
exmh-async emacsclient
exmh-async xterm -e vi
exmh-async xterm {-geom 80x44+0+0} -e vi" \
    [list \
	[list editor(prog) editCmd $prog {Editor command} \
"The editor command used to compose mail messages.
The filename will be appended to the command."] \
	[list editor(alternate) edit2Cmd {exmh-async emacs} {2nd Editor command} \
"This is an alternate editor command.  For example, if your default
editor is sedit, you might want to drop into emacs for a particular
message.  The filename will be appended to the command."] \
	[list editor(autowhom) autoWhom ON {Auto Whom} \
"Enabling this causes whom to be invoked automatically whenever a
What Now? dialog is displayed."] \
	[list editor(sedit!) seditOverride OFF {Sedit override} \
"Use this to override the regular editor command and
use the built-in editor instead.  This parameter is set
initially by the command line -sedit switch."] \
	[list editor(async_sedit) seditAfterAsync OFF {Use Sedit after Async} \
"If enabled, after editing with external editor, exmh will bring the message
up in sedit.  This is so you can initially create the message with your
favorite editor, and then pop into to sedit for richtext or attachments."] \
        [list editor(mhn) mhnCmd "mhn" {MHN command} \
"The mhn command specifies a program used to reformat
a message with the MH mhn program.
The filename will be appended to the command."] \
    ]
    set editor(sedit) sedit
}

proc Edit_Draft {} {
    global mhProfile exmh
    # Run the editor on the current draft
    set draftID [Mh_Cur $mhProfile(draft-folder)]
    if {$draftID == {}} {
	Exmh_Status "No current message in Draft-Folder $mhProfile(draft-folder)" error
	return
    }
    EditWhatNow $draftID prog
}
proc Edit_DraftID { id } {
    global exmh
    # No mucking with context. We normally get here by-passing the
    # standard draft creation process. Hence we need to set exmh($id,action)
    set exmh($id,action) auto
    EditWhatNow $id prog
}

proc EditDraftFolderHook { f what } {
    # Called when we change to the drafts folder
    Buttons_DraftMode 1
}
proc EditDraftFolderCleanup { f what } {
    Buttons_DraftMode 0
}

# Throw up a dialog asking whether user wants to
# send, re-edit, save as draft, abort.
# As with the command line whatnowproc, this also starts up the
# editor on the draft.

proc EditWhatNow {draftID {edittype prog}} {
    global mhProfile editor

    if {([string compare $edittype prog] == 0) && $editor(sedit!)} {
	set edittype sedit	;# sedit override
    }
    Exmh_Debug EditWhatNow $draftID $edittype
    if ![regexp {^[0-9]+$} $draftID] {
	# Must be a message in a non-drafts folder
	set path $mhProfile(path)/$draftID
    } else {
	# Delete ".orig" file if it exists, Mhn_* thanks to Colm Buckley
	Mhn_DeleteOrig $draftID
	set path [Mh_Path $mhProfile(draft-folder) $draftID]
    }
    if [EditStart $path $edittype] {
	# Editor has run synchronously, so we go right into the dialog
	Edit_Dialog $draftID
    }
    global exmh
    if {[string compare $exmh(folder) $mhProfile(draft-folder)] == 0} {
	# It isn't safe to leave a current message active in the drafts
	# folder because a second edit can loose changes in the first.
	# User saves a draft.
	# User changes to draft folder.
	# The "Send" button uses the saved draft, and they make edits.
	# Another "Send" button hit resets the draft to their last save,
	# but they probably expected to start a new draft.
	Msg_ClearCurrent
    }
}

# The following can be invoked by remote editor interpreters
proc Edit_Dialog {draftID} {
    global exmh mhProfile editor
    Exmh_Debug Edit_Dialog $draftID
    if {$editor(async_sedit)} {
	Sedit_Start $mhProfile(path)/$mhProfile(draft-folder)/$draftID
    } else {
	EditShowDialog $draftID "What should I do with draft $draftID?"
    }
}
# For compatibility with old versions of mxedit
proc EditDialog {draftID} {
    Edit_Dialog $draftID
}

# Turn passphrase pane ON/OFF/disabled depending on pgp(seditpgp) and
# pgp(keeppass)
proc EditMaybeAddPhrasePane {id w} {
    global pgp

    if {!$pgp(enabled)} {
	return
    }

    set dismsg "Disabled since passphrases are not being kept."
    if {$pgp(seditpgp)} {
	# Need to add pane
	if {[lsearch [pack slaves $w] $w.pgp] < 0} {
	    EditAddPassPhrasePane $id $w
	}
	# Just in case the user is playing with pgp(keeppass) value
	if {$pgp(echopass)} {
	    $w.pgp.e configure -show * -state normal
	} else {
	    $w.pgp.e configure -show {} -state normal
	}
	if {![string compare $pgp(cur,pass,$id) $dismsg]} {
	    set pgp(cur,pass,$id) {}
	}
    } else {
	# Need to take away the pane (if it is there)
	if {[lsearch [pack slaves $w] $w.pgp] >= 0} {
	    destroy $w.pgp
	}
    }

    if {!$pgp(keeppass) && [lsearch [pack slaves $w] $w.pgp] >= 0} {
	# Need to disable the pane (if it is there)
	set pgp(cur,pass,$id) $dismsg
	$w.pgp.e configure -show {} -state disabled
    }
}

proc EditAddPassPhrasePane {id w} {
    global pgp
    if {$pgp(enabled) && $pgp(seditpgp)} {

	# seditpgp main area
	Pgp_SetSeditPgpName $pgp($pgp(version,$id),myname,$id) $id
	set pgp(fullName,$id) $pgp($pgp(version,$id),fullName)

	if {![winfo exists $w.pgp]} {
	    pack [frame $w.pgp] -side bottom -fill x -ipady 2
	}
	if {![winfo exists $w.pgp.l1]} {
	    pack [label $w.pgp.l1 -text "Passphrase for "] \
		    -side left
	}
	if {![winfo exists $w.pgp.b]} {
	    pack [button $w.pgp.b -textvariable pgp(sedit_label,$id) \
		    -command "Pgp_SetMyName \$pgp(version,$id) $id"] \
		    -side left -ipady 2
	}
	if {![winfo exists $w.pgp.l2]} {
	    pack [label $w.pgp.l2 -text ": "] \
		    -side left
	}
	if {![winfo exists $w.pgp.e]} {
	    pack [entry $w.pgp.e -textvariable pgp(cur,pass,$id)] \
		    -side left -expand yes -fill x -ipady 2
	    if {$pgp(echopass)} {
		$w.pgp.e configure -show *
	    }
	}

	# Add extras if requested
	if {$pgp(seditpgpextras)} {
	    if {![winfo exists $w.pgp2]} {
		pack [frame $w.pgp2] -side bottom -fill x
	    }
	    if {![winfo exists $w.pgp2.l1]} {
		pack [label $w.pgp2.l1 -textvariable pgp(sedit_label2,$id)] -side left
	    }
	}
    }
}
proc EditShowDialog {id text} {
    global exwin editor pgp
    # Create the buttons and arrange them from left to right in the RH
    # frame. Embed the left button in an additional sunken frame to indicate
    # that it is the default button.

    if [Exwin_Toplevel .edit$id "What Now?" WhatNow nomenu] {
	set d .edit$id
	wm transient $d
	$d config -relief raised -borderwidth 2

	# PGP version-setting moved out from seditpgp code
	if {$pgp(enabled)} {
	    if {![info exists pgp($pgp(version,$id),myname,$id)]} {
		set pgp($pgp(version,$id),myname,$id) $pgp($pgp(version,$id),myname)
	    }
	    EditMaybeAddPhrasePane $id $d
	}

	foreach but [Widget_GetButDef $d] {
	    Widget_AddButDef $d $but {right}
	    Widget_ReEvalCmd $d.$but	;# expand $id variable now
	}
	catch {pack $d.abort -padx 15}
	catch {pack $d.send -ipady 5 -ipadx 5 -padx 5}

	foreach M [Widget_GetMenuBDef $d] {
	    set menu [Widget_AddMenuBDef $d $M {right padx 1}]
	    ButtonMenuInner $menu	;# This also expands variables
	}

	# Make sure only valid entries are enabled in version submenu
	# otherwise things may fail in post-processing.
	# We don't have to take care of the active entry since 
	# preferences only allows valid entries as initial version
	if {$pgp(enabled)} {
	    set submenu $d.more.m.encrypt.version
	    for {set sm 0} {$sm<=[$submenu index last]} {incr sm} {
		if [catch {$submenu entrycget $sm -value} v] {
		    continue
		}
		if {[info exists pgp($v,enabled)] && \
			!$pgp($v,enabled) } {
		    $submenu entryconfigure $sm -state disabled
		}
	    }
	}

	Widget_Message $d msg -text "$text\nReturn for Send\nControl-c for Kill" -aspect 400

	focus $d
	bind $d <Return> [list $d.send invoke]
	bind $d <Control-c> [list $d.abort invoke]

	Visibility_Wait .edit$id
	Exmh_Focus
    } else {
	set d .edit$id
        catch {destroy $d.f}	;# Whom results
	EditMaybeAddPhrasePane $id $d
    }
    if $editor(autowhom) {
	EditDialogDone whom $id nohide
    }
}
proc EditDialogMsg {id msg} {
    set d .edit$id
    catch {destroy $d.f}
    Widget_Frame $d f
    pack $d.f -before [lindex [pack slaves $d] 0] -side bottom
    set lines [llength [split $msg \n]]
    Widget_Text $d.f [expr {$lines > 8 ? 8 : $lines}]
    $d.f.t insert 1.0 $msg
    $d.f.t config -state disabled -width 40
}
proc EditDialogDone {act id {hide hide}} {
    if [string match hide $hide] {
	Exwin_Dismiss .edit$id nosize
    }
    Edit_Done $act $id {}
}

proc EditStart { draft {type prog} } {
    # Start the editor, reusing an existing session if possible
    global editor exmh mhProfile pgp install

    Exmh_Debug EditStart $draft $type

    if $pgp(enabled) {
	# Copy the default PGP values into this window only if they
	# don't already exists. This way, we preserve values between
	# re-edit sessions. Edit_Done takes care of resetting to 
	# preference values when we send or abort (ie. get done draft).
	set id [SeditId $draft]
	foreach var {encrypt sign format version} {
	    if ![info exists pgp($var,$id)] {
		set pgp($var,$id) $pgp($var)
	    }
	}
    }
    
    switch -glob -- $editor($type) {
	*mxedit* {
	    if ![info exists exmh(editInterp)] {
		set exmh(editInterp) "mxedit"
	    }
	    if ![info exists exmh(mxeditVersion)] {
		if ![catch {send $exmh(editInterp) {set mxVersion}} vers] {
		    set exmh(mxeditVersion) $vers
		}
	    }
	    set id "$exmh(editInterp) $draft"
	    if [info exists exmh(mxeditVersion)] {
		if {$exmh(mxeditVersion) >= 2.4} {
		    global env
		    if [regsub $env(HOME) $draft ~ newpath] {
			set id "$exmh(editInterp) $newpath"
		    }
		}
	    }
	    Exmh_Debug mxReset $id
	    if [catch {send $id mxReset}] {
		if [catch {send $exmh(editInterp) {set mxVersion}}] {
		    Exmh_Status "Starting mxedit..." warn
		    # Start the editor and tell it to make a callback
		    # that identifies the TCL interpreter in the editor
		    eval exec $editor($type) {-globalCmd [list mxSendInterpName [winfo name .] Edit_Ident] $draft &}
		} else {
		    Exmh_Status "Opening mxedit..." warn
		    catch {send $exmh(editInterp) [list mxOpen $draft]}
		}
	    } else {
		Exmh_Status "Reopening mxedit..." warn
		catch {send $id {wm deiconify .}}
	    }
	    return 0		;# Asynchronous edit
	}
	sedit {
	    Sedit_Start $draft
	    return 0		;# Asynchronous edit
	}
	exmh-async* {
	    global wish argv0
	    Exmh_Status "Starting ASYNC $editor($type) ..." warn
	    eval {exec $wish -f $install(dir,bin)/exmh-async -- [winfo name .]} \
		[lrange $editor($type) 1 end] {$draft &}
	    return 0		;# Asynchronous edit
	}
	give-away* -
	gnuclient*& -
	emacsclient*& {
	    set cmd $editor($type)	;# Tcl 7.0 bug in regsub
	    regsub ^give-away $cmd {} cmd
            set cmd [string trimright $cmd "& \t"]
	    Exmh_Status "Starting $cmd ..." warn
            if [catch {eval exec $cmd $draft &} err] {
                Exmh_Status $err error
            }
	    return 0		;# Asynchronous edit

	}
	*& {
	    Exmh_Status "Starting TK $editor($type) ..." warn
            set cmd [string trimright $editor($type) "& \t"]
            if [catch {eval exec $cmd \"[winfo name .]\" $draft &} err] {
                Exmh_Status $err error
            }
	    return 0		;# Asynchronous edit

	}
	default {
	    Exmh_Status "Starting $editor($type) ..." warn
	    if [catch {eval exec $editor($type) $draft} err] {
		Exmh_Status $err error
	    }
	    return 1		;# Synchronous edit
	}
    }
}

# The following is invoked via "send" by mxedit when it
# starts up the first time in order to identify itself to us.

proc Edit_Ident { interpName } {
    global exmh
    set exmh(editInterp) $interpName
}

# The following is invoked by remote editor interpreters
proc EditDone {act msg argu} {
    Edit_Done $act $msg $argu
}
proc Edit_Done {act {msg cur} argu} {
    # Commit or abort an edit session
    global mhProfile exmh env editor pgp
    if {$msg == "cur"} {
	set msg [Mh_Cur $mhProfile(draft-folder)]
	if {$msg == {}} {
	    Exmh_Status "No current draft"
	    return
	}
    }
    Exmh_Debug Edit_Done action = $act msg = $msg
    if ![regexp {^[0-9]+$} $msg] {
	# Message not in the drafts folder
	set path $mhProfile(path)/$msg
    }
    case $act in {
	send	{
	    Aliases_CheckPoint
	    if [info exists path] {
		# Copy message to drafts folder
		set id [file tail [Mh_Path $mhProfile(draft-folder) new]]
		Exmh_Status "Copying $msg to draft $id"
		MhExec comp +[file dirname $msg] [file tail $msg] -nowhatnowproc
		set msg $id
	    }
	    set anno [Mh_AnnoEnviron $msg]
	    Exmh_Debug Edit_Done send: anno=$anno
	    Exmh_Debug "Mh_Send [time {set code [catch {Mh_Send $msg $argu} err2]}]"
	    if $code {
		# move the orig message back to the draft if it exists
		Mhn_RenameOrig $msg
		Exmh_Status $err2 error
		Send_Error $err2 $msg
		return
	    }
	    if {$exmh(folder) == $mhProfile(draft-folder)} {
		# Clean up scan listing
		if [catch {Msg_RemoveById $msg} err] {
		    Exmh_Debug Msg_RemoveById $msg $err
		}
	    }
	    Exmh_Status "Draft $msg sent" normal
	    # Delete "orig" message if it exists
	    Mhn_DeleteOrig $msg
	    Quote_Cleanup
	    if {$anno} {
		if {[string compare $exmh($msg,folder) $exmh(folder)] == 0} {
		    foreach lineno [Ftoc_FindMsgs $exmh($msg,mhmessages)] {
			Exmh_Debug Edit_Done lineno=$lineno
			if {$lineno != {}} {
			    Ftoc_RescanLine $lineno dash
			}
		    }
		}
	    }
	    Mh_AnnoCleanup $msg
	    if $pgp(enabled) {
		# Done with this draft, set PGP defaults for next call
		set id [SeditId $msg]
		foreach var {encrypt sign format version} {
		    set pgp($var,$id) $pgp($var)
		}
	    }
	}
	reedit	{
	    Exmh_Status " "
            # Rename the orig message back to the draft
	    Mhn_RenameOrig $msg
	    EditWhatNow $msg prog
	}
	sedit	{
	    Exmh_Status " "
	    EditWhatNow $msg sedit
	}
	alternate {
	    Exmh_Status " "
	    EditWhatNow $msg alternate
	}
        spell {
            Exmh_Status " "
            EditWhatNow $msg spell
        }
        mhn {
	    # If the orig file exists, move it back to the draft
	    Mhn_RenameOrig $msg
	    if [info exists path] {
		set env(mhdraft) $path
	    } else {
		set env(mhdraft) [Mh_Path $mhProfile(draft-folder) $msg]
	    }
	    if [catch {exec $editor(mhn) $env(mhdraft)} err] {
		EditDialogMsg $msg "MHN failed: $err"
	    } else {
		EditDialogMsg $msg "MHN returned a-o.k."
	    }
        }
	abort	{
	    if ![info exists path]  {
		catch {Mh_Rmm $mhProfile(draft-folder) $msg}
		Mhn_DeleteOrig $msg
		if {$exmh(folder) == $mhProfile(draft-folder)} {
		    # Clean up scan listing
		    if [catch {Msg_RemoveById $msg} err] {
			Exmh_Debug Msg_RemoveById $msg $err
		    }
		}
		Exmh_Status "Draft $msg aborted" error
		Quote_Cleanup
		Mh_AnnoCleanup $msg
		if $pgp(enabled) {
		    # Done with this draft, set PGP defaults for next call
		    set id [SeditId $msg]
		    foreach var {encrypt sign format version} {
			set pgp($var,$id) $pgp($var)
		    }
		}
	    }
	}
	dismiss	{
	    Exmh_Status "Draft $msg dismissed" normal
	    Quote_Cleanup
	    Mhn_RenameOrig $msg
	    Mh_AnnoCleanup $msg
	}
	whom	{
	    Mh_AnnoEnviron $msg
	    if [info exists path] {
		catch {Mh_Whom $path} result
	    } else {
		catch {Mh_Whom $msg} result
	    }
	    EditDialogMsg $msg $result
	}
	default	{
	    Exmh_Error "Unknown action in Edit_Done"
	}
    }
}