docs/master
view discussion.roff @ 123:740f4128dea7
Reworked and extended the text about Modularization.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Sat, 30 Jun 2012 15:00:04 +0200 |
parents | c234656329e0 |
children | 3d30fd938aa9 |
line source
1 .H0 "Discussion
2 .P
3 This main chapter discusses the practical work done in the mmh project.
4 It is structured along the goals to achieve.
5 The concrete work done
6 is described in the examples of how the general goals were achieved.
7 The discussion compares the current version of mmh with the state of
8 nmh just before the mmh project started, i.e. Fall 2011.
9 Current changes of nmh will be mentioned only as side notes.
10 .\" XXX where do I discuss the parallel development of nmh?
14 .H1 "Stream-Lining
16 .P
17 MH had been considered an all-in-one system for mail handling.
18 The community around nmh has a similar understanding.
19 In fundamental difference, mmh shall be a MUA only.
20 I believe that the development of all-in-one mail systems is obsolete.
21 Today, email is too complex to be fully covered by single projects.
22 Such a project won't be able to excel in all aspects.
23 Instead, the aspects of email should be covered my multiple projects,
24 which then can be combined to form a complete system.
25 Excellent implementations for the various aspects of email exist already.
26 Just to name three examples: Postfix is a specialized MTA,
27 Procmail is a specialized MDA, and Fetchmail is a specialized MRA.
28 I believe that it is best to use such specialized tools instead of
29 providing the same function again as a side-component in the project.
30 .P
31 Doing something well, requires to focus on a small set of specific aspects.
32 Under the assumption that focused development produces better results
33 in the particular area, specialized projects will be superior
34 in their field of focus.
35 Hence, all-in-one mail system projects \(en no matter if monolithic
36 or modular \(en will never be the best choice in any of the fields.
37 Even in providing the best consistent all-in-one system they are likely
38 to be beaten by projects that focus only on integrating existing mail
39 components to a homogeneous system.
40 .P
41 The limiting resource in Free Software community development
42 is usually man power.
43 If the development power is spread over a large development area,
44 it becomes even more difficult to compete with the specialists in the
45 various fields.
46 The concrete situation for MH-based mail systems is even tougher,
47 given the small and aged community, including both developers and users,
48 it has.
49 .P
50 In consequence, I believe that the available development resources
51 should focus on the point where MH is most unique.
52 This is clearly the user interface \(en the MUA.
53 Peripheral parts should be removed to stream-line mmh for the MUA task.
56 .H2 "Mail Transfer Facilities
57 .P
58 In contrast to nmh, which also provides mail submission and mail retrieval
59 agents, mmh is a MUA only.
60 This general difference initiated the development of mmh.
61 Removing the mail transfer facilities had been the first work task
62 in the mmh project.
63 .P
64 Focusing on one mail agent role only is motivated by Eric Allman's
65 experience with Sendmail.
66 He identified limiting Sendmail the MTA task had be one reason for
67 its success:
68 .[ [
69 costales sendmail
70 .], p. xviii]
71 .QS
72 Second, I limited myself to the routing function \(en
73 I wouldn't write user agents or delivery back-ends.
74 This was a departure of the dominant through of the time,
75 in which routing logic, local delivery, and often the network code
76 were incorporated directly into the user agents.
77 .QE
78 .P
79 In mmh, the Mail Submission Agent (MSA) is called
80 \fIMessage Transfer Service\fP (MTS).
81 This facility, implemented by the
82 .Pn post
83 command, established network connections and spoke SMTP to submit
84 messages for relay to the outside world.
85 The changes in email demanded changes in this part of nmh too.
86 Encryption and authentication for network connections
87 needed to be supported, hence TLS and SASL were introduced into nmh.
88 This added complexity to nmh without improving it in its core functions.
89 Also, keeping up with recent developments in the field of
90 mail transfer requires development power and specialists.
91 In mmh this whole facility was simply cut off.
92 .Ci f6aa95b724fd8c791164abe7ee5468bf5c34f226
93 .Ci fecd5d34f65597a4dfa16aeabea7d74b191532c3
94 .Ci 156d35f6425bea4c1ed3c4c79783dc613379c65b
95 Instead, mmh depends on an external MSA.
96 The only outgoing interface available to mmh is the
97 .Pn sendmail
98 command, which almost any MSA provides.
99 If not, a wrapper program can be written.
100 It must read the message from the standard input, extract the
101 recipient addresses from the message header, and hand the message
102 over to the MSA.
103 For example, a wrapper script for qmail would be:
104 .VS
105 #!/bin/sh
106 # ignore command line arguments
107 exec qmail-inject
108 VE
109 The requirement to parse the recipient addresses out of the message header
110 is likely to be removed in the future.
111 Then mmh would give the recipient addresses as command line arguments.
112 This appears to be the better interface.
113 .\" XXX implement it
114 .P
115 To retrieve mail, the
116 .Pn inc
117 command acted as Mail Retrieval Agent (MRA).
118 It established network connections
119 and spoke POP3 to retrieve mail from remote servers.
120 As with mail submission, the network connections required encryption and
121 authentication, thus TLS and SASL were added.
122 Support for message retrieval through IMAP will become necessary
123 to be added soon, too, and likewise for any other changes in mail transfer.
124 Not so for mmh because it has dropped the support for retrieving mail
125 from remote locations.
126 .Ci ab7b48411962d26439f92f35ed084d3d6275459c
127 Instead, it depends on an external tool to cover this task.
128 In mmh exist two paths for messages to enter mmh's mail storage:
129 (1) Mail can be incorporated with
130 .Pn inc
131 from the system maildrop, or (2) with
132 .Pn rcvstore
133 by reading them, one at a time, from the standard input.
134 .P
135 With the removal of the MSA and MRA, mmh converted from an all-in-one
136 mail system to being a MUA only.
137 Now, of course, mmh depends on third-party software.
138 An external MSA is required to transfer mail to the outside world;
139 an external MRA is required to retrieve mail from remote machines.
140 There exist excellent implementations of such software,
141 which do this specific task likely better than the internal
142 versions had done it.
143 Also, the best suiting programs can be freely chosen.
144 .P
145 As it had already been possible to use an external MSA or MRA,
146 why not keep the internal version for convenience?
147 The question whether there is sense in having a fall-back pager in all
148 the command line tools, for the cases when
149 .Pn more
150 or
151 .Pn less
152 aren't available, appears to be ridiculous.
153 Of course, MSAs and MRAs are more complex than text pagers
154 and not necessarily available but still the concept of orthogonal
155 design holds: ``Write programs that do one thing and do it well.''
156 .[
157 mcilroy unix phil
158 p. 53
159 .]
160 .[
161 mcilroy bstj foreword
162 .]
163 Here, this part of the Unix philosophy was applied not only
164 to the programs but to the project itself.
165 In other words:
166 ``Develop projects that focus on one thing and do it well.''
167 Projects grown complex should be split for the same reasons programs grown
168 complex should be split.
169 If it is conceptionally more elegant to have the MSA and MRA as
170 separate projects then they should be separated.
171 This is the case here, in my opinion.
172 The RFCs propose this separation by clearly distinguishing the different
173 mail handling tasks.
174 .[
175 rfc 821
176 .]
177 The small interfaces between the mail agents support the separation.
178 .P
179 In the beginning, email had been small and simple.
180 At that time,
181 .Pn /bin/mail
182 had covered anything there was to email and still had been small
183 and simple.
184 Later, the essential complexity of email increased.
185 (Essential complexity is the complexity defined by the problem itself.\0
186 .[[
187 brooks no silver bullet
188 .]])
189 Email systems reacted to this change: They grew.
190 RFCs started to introduce the concept of mail agents to separate the
191 various tasks because they became more extensive and new tasks appeared.
192 As the mail systems grew even more, parts were split off.
193 In nmh, for instance, the POP server, which was included in the original
194 MH, was removed.
195 Now is the time to go one step further and split the MSA and MRA off, too.
196 Not only does this decrease the code size of the project,
197 but, more important, it unburdens mmh of the whole field of
198 message transfer with all its implications for the project.
199 There is no more need to concern with changes in network transfer.
200 This independence is received by depending on an external program
201 that covers the field.
202 Today, this is a reasonable exchange.
203 .P
204 Functionality can be added in three different ways:
205 .BU
206 Implementing the function originally in the project.
207 .BU
208 Depending on a library that provides the function.
209 .BU
210 Depending on a program that provides the function.
211 .P
212 Whereas adding the function originally to the project increases the
213 code size most and requires most maintenance and development work,
214 it makes the project most independent of other software.
215 Using libraries or external programs require less maintenance work
216 but introduces dependencies on external software.
217 Programs have the smallest interfaces and provide the best separation
218 but possibly limit the information exchange.
219 External libraries are stronger connected than external programs,
220 thus information can be exchanged more flexible.
221 Adding code to a project increases maintenance work.
222 .\" XXX ref
223 Implementing complex functions originally in the project adds
224 a lot of code.
225 This should be avoided if possible.
226 Hence, the dependencies only change in kind, not in their existence.
227 In mmh, library dependencies on
228 .Pn libsasl2
229 and
230 .Pn libcrypto /\c
231 .Pn libssl
232 were treated against program dependencies on an MSA and an MRA.
233 This also meant treating build-time dependencies against run-time
234 dependencies.
235 Besides program dependencies providing the stronger separation
236 and being more flexible, they also allowed
237 over 6\|000 lines of code to be removed from mmh.
238 This made mmh's code base about 12\|% smaller.
239 Reducing the project's code size by such an amount without actually
240 losing functionality is a convincing argument.
241 Actually, as external MSAs and MRAs are likely superior to the
242 project's internal versions, the common user even gains functionality.
243 .P
244 Users of MH should not have problems to set up an external MSA and MRA.
245 Also, the popular MSAs and MRAs have large communities and a lot
246 of documentation available.
247 Choices for MSAs range from full-featured MTAs like
248 .I Postfix
249 over mid-size MTAs like
250 .I masqmail
251 and
252 .I dma
253 to small forwarders like
254 .I ssmtp
255 and
256 .I nullmailer .
257 Choices for MRAs include
258 .I fetchmail ,
259 .I getmail ,
260 .I mpop
261 and
262 .I fdm .
265 .H2 "Non-MUA Tools
266 .P
267 One goal of mmh is to remove the tools that are not part of the MUA's task.
268 Further more, any tools that don't improve the MUA's job significantly
269 should be removed.
270 Loosely related and rarely used tools distract from the lean appearance.
271 They require maintenance work without adding much to the core task.
272 By removing these tools, the project shall become more stream-lined
273 and focused.
274 In mmh the following tools are not available anymore:
275 .BU
276 .Pn conflict
277 was removed
278 .Ci 8b235097cbd11d728c07b966cf131aa7133ce5a9
279 because it is a mail system maintenance tool that is not MUA-related.
280 It even checked
281 .Fn /etc/passwd
282 and
283 .Fn /etc/group
284 for consistency, which is completely unrelated to email.
285 A tool like
286 .Pn conflict
287 is surely useful, but it should not be shipped with mmh.
288 .\" XXX historic reasons?
289 .BU
290 .Pn rcvtty
291 was removed
292 .Ci 14767c94b3827be7c867196467ed7aea5f6f49b0
293 because its use case of writing to the user's terminal
294 on receiving of mail is obsolete.
295 If users like to be informed of new mail, the shell's
296 .Ev MAILPATH
297 variable or graphical notifications are technically more appealing.
298 Writing directly to terminals is hardly ever wanted today.
299 If though one wants to have it this way, the standard tool
300 .Pn write
301 can be used in a way similar to:
302 .VS
303 scan -file - | write `id -un`
304 VE
305 .BU
306 .Pn viamail
307 was removed
308 .Ci eda72d6a7a7c20ff123043fb7f19c509ea01f932
309 when the new attachment system was activated, because
310 .Pn forw
311 could then cover the task itself.
312 The program
313 .Pn sendfiles
314 was rewritten as a shell script wrapper around
315 .Pn forw .
316 .Ci 0e82199cf3c991a173e0ac8aa776efdb3ded61e6
317 .BU
318 .Pn msgchk
319 was removed
320 .Ci bb9360ead7eb7a3fedcce2eeedfc660014e41dbe ,
321 because it lost its use case when POP support was removed.
322 A call to
323 .Pn msgchk
324 provided hardly more information than:
325 .VS
326 ls -l /var/mail/meillo
327 VE
328 It did distinguish between old and new mail, but
329 this detail information can be retrieved with
330 .Pn stat (1),
331 too.
332 A small shell script could be written to print the information
333 in a similar way, if truly necessary.
334 As mmh's
335 .Pn inc
336 only incorporates mail from the user's local maildrop,
337 and thus no data transfers over slow networks are involved,
338 there's hardly any need to check for new mail before incorporating it.
339 .BU
340 .Pn msh
341 was removed
342 .Ci 916690191222433a6923a4be54b0d8f6ac01bd02
343 because the tool was in conflict with the philosophy of MH.
344 It provided an interactive shell to access the features of MH,
345 but it wasn't just a shell, tailored to the needs of mail handling.
346 Instead it was one large program that had several MH tools built in.
347 This conflicts with the major feature of MH of being a tool chest.
348 .Pn msh 's
349 main use case had been accessing Bulletin Boards, which have seized to
350 be popular.
351 .P
352 Removing
353 .Pn msh ,
354 together with the truly archaic code relicts
355 .Pn vmh
356 and
357 .Pn wmh ,
358 saved more than 7\|000 lines of C code \(en
359 about 15\|% of the project's original source code amount.
360 Having less code \(en with equal readability, of course \(en
361 for the same functionality is an advantage.
362 Less code means less bugs and less maintenance work.
363 As
364 .Pn rcvtty
365 and
366 .Pn msgchk
367 are assumed to be rarely used and can be implemented in different ways,
368 why should one keep them?
369 Removing them stream-lines mmh.
370 .Pn viamail 's
371 use case is now partly obsolete and partly covered by
372 .Pn forw ,
373 hence there's no reason to still maintain it.
374 .Pn conflict
375 is not related to the mail client, and
376 .Pn msh
377 conflicts with the basic concept of MH.
378 Theses two tools might still be useful, but they should not be part of mmh.
379 .P
380 Finally, there's
381 .Pn slocal .
382 .Pn slocal
383 is an MDA and thus not directly MUA-related.
384 It should be removed from mmh, because including it conflicts with
385 the idea that mmh is a MUA only.
386 .Pn slocal
387 should rather become a separate project.
388 However,
389 .Pn slocal
390 provides rule-based processing of messages, like filing them into
391 different folders, which is otherwise not available in mmh.
392 Although
393 .Pn slocal
394 does neither pull in dependencies nor does it include a separate
395 technical area (cf. Sec. XXX), still,
396 it accounts for about 1\|000 lines of code that need to be maintained.
397 As
398 .Pn slocal
399 is almost self-standing, it should be split off into a separate project.
400 This would cut the strong connection between the MUA mmh and the MDA
401 .Pn slocal .
402 For anyone not using MH,
403 .Pn slocal
404 would become yet another independent MDA, like
405 .I procmail .
406 Then
407 .Pn slocal
408 could be installed without the complete MH system.
409 Likewise, mmh users could decide to use
410 .I procmail
411 without having a second, unused MDA,
412 .Pn slocal ,
413 installed.
414 That appears to be conceptionally the best solution.
415 Yet,
416 .Pn slocal
417 is not split off.
418 I defer the decision over
419 .Pn slocal
420 in need for deeper investigation.
421 In the meanwhile, it remains part of mmh.
422 That does not hurt because
423 .Pn slocal
424 is unrelated to the rest of the project.
427 .H2 "\fLshow\fP and \fPmhshow\fP
428 .P
429 Since the very beginning \(en already in the first concept paper \(en
430 .Pn show
431 had been MH's message display program.
432 .Pn show
433 mapped message numbers and sequences to files and invoked
434 .Pn mhl
435 to have the files formatted.
436 With MIME, this approach wasn't sufficient anymore.
437 MIME messages can consist of multiple parts. Some parts are not
438 directly displayable and text content might be encoded in
439 foreign charsets.
440 .Pn show 's
441 understanding of messages and
442 .Pn mhl 's
443 display capabilities couldn't cope with the task any longer.
444 .P
445 Instead of extending these tools, additional tools were written from
446 scratch and added to the MH tool chest.
447 Doing so is encouraged by the tool chest approach.
448 Modular design is a great advantage for extending a system,
449 as new tools can be added without interfering with existing ones.
450 First, the new MIME features were added in form of the single program
451 .Pn mhn .
452 The command
453 .Cl "mhn -show 42
454 would show the MIME message numbered 42.
455 With the 1.0 release of nmh in February 1999, Richard Coleman finished
456 the split of
457 .Pn mhn
458 into a set of specialized tools, which together covered the
459 multiple aspects of MIME.
460 One of them was
461 .Pn mhshow ,
462 which replaced
463 .Cl "mhn -show" .
464 It was capable of displaying MIME messages appropriately.
465 .P
466 From then on, two message display tools were part of nmh,
467 .Pn show
468 and
469 .Pn mhshow .
470 To ease the life of users,
471 .Pn show
472 was extended to automatically hand the job over to
473 .Pn mhshow
474 if displaying the message would be beyond
475 .Pn show 's
476 abilities.
477 In consequence, the user would simply invoke
478 .Pn show
479 (possibly through
480 .Pn next
481 or
482 .Pn prev )
483 and get the message printed with either
484 .Pn show
485 or
486 .Pn mhshow ,
487 whatever was more appropriate.
488 .P
489 Having two similar tools for essentially the same task is redundant.
490 Usually,
491 users wouldn't distinguish between
492 .Pn show
493 and
494 .Pn mhshow
495 in their daily mail reading.
496 Having two separate display programs was therefore mainly unnecessary
497 from a user's point of view.
498 Besides, the development of both programs needed to be in sync,
499 to ensure that the programs behaved in a similar way,
500 because they were used like a single tool.
501 Different behavior would have surprised the user.
502 .P
503 Today, non-MIME messages are rather seen to be a special case of
504 MIME messages, although it is the other way round.
505 As
506 .Pn mhshow
507 had already be able to display non-MIME messages, it appeared natural
508 to drop
509 .Pn show
510 in favor of using
511 .Pn mhshow
512 exclusively.
513 .Ci 4c1efddfd499300c7e74263e57d8aa137e84c853
514 Removing
515 .Pn show
516 is no loss in function, because functionally
517 .Pn mhshow
518 covers it completely.
519 The old behavior of
520 .Pn show
521 can still be emulated with the simple command line:
522 .VS
523 mhl `mhpath c`
524 VE
525 .P
526 For convenience,
527 .Pn mhshow
528 was renamed to
529 .Pn show
530 after
531 .Pn show
532 was gone.
533 It is clear that such a rename may confuse future developers when
534 trying to understand the history.
535 Nevertheless, I consider the convenience on the user's side,
536 to call
537 .Pn show
538 when they want a message to be displayed, to outweigh the inconvenience
539 on the developer's side when understanding the project history.
540 .P
541 To prepare for the transition,
542 .Pn mhshow
543 was reworked to behave more like
544 .Pn show
545 first.
546 (cf. Sec. XXX)
547 Once the tools behaved more alike, the replacing appeared to be
548 even more natural.
549 Today, mmh's new
550 .Pn show
551 became the one single message display program again, with the difference
552 that today it handles MIME messages as well as non-MIME messages.
553 The outcome of the transition is one program less to maintain,
554 no second display program for users to deal with,
555 and less system complexity.
556 .P
557 Still, removing the old
558 .Pn show
559 hurts in one regard: It had been such a simple program.
560 Its lean elegance is missing to the new
561 .Pn show .
562 But there is no chance;
563 supporting MIME demands for higher essential complexity.
566 .H2 "Configure Options
567 .P
568 Customization is a double-edged sword.
569 It allows better suiting setups, but not for free.
570 There is the cost of code complexity to be able to customize.
571 There is the cost of less tested setups, because there are
572 more possible setups and especially corner-cases.
573 And, there is the cost of choice itself.
574 The code complexity directly affects the developers.
575 Less tested code affects both, users and developers.
576 The problem of choice affects the users, for once by having to
577 choose, but also by more complex interfaces that require more documentation.
578 Whenever options add little advantages, they should be considered for
579 removal.
580 I have reduced the number of project-specific configure options from
581 fifteen to three.
583 .U3 "Mail Transfer Facilities
584 .P
585 With the removal of the mail transfer facilities five configure
586 options vanished:
587 .P
588 The switches
589 .Sw --with-tls
590 and
591 .Sw --with-cyrus-sasl
592 had activated the support for transfer encryption and authentication.
593 This is not needed anymore.
594 .Ci fecd5d34f65597a4dfa16aeabea7d74b191532c3
595 .Ci 156d35f6425bea4c1ed3c4c79783dc613379c65b
596 .P
597 The configure switch
598 .Sw --enable-pop
599 activated the message retrieval facility.
600 The code area that would be conditionally compiled in for TLS and SASL
601 support had been small.
602 The conditionally compiled code area for POP support had been much larger.
603 Whereas the code base changes would only slightly change on toggling
604 TLS or SASL support, it changed much on toggling POP support.
605 The changes in the code base could hardly be overviewed.
606 By having POP support togglable a second code base had been created,
607 one that needed to be tested.
608 This situation is basically similar for the conditional TLS and SASL
609 code, but there the changes are minor and can yet be overviewed.
610 Still, conditional compilation of a code base creates variations
611 of the original program.
612 More variations require more testing and maintenance work.
613 .P
614 Two other options only specified default configuration values:
615 .Sw --with-mts
616 defined the default transport service, either
617 .Ar smtp
618 or
619 .Ar sendmail .
620 In mmh this fixed to
621 .Ar sendmail .
622 .Ci f6aa95b724fd8c791164abe7ee5468bf5c34f226
623 With
624 .Sw --with-smtpservers
625 default SMTP servers for the
626 .Ar smtp
627 transport service could be specified.
628 .Ci 128545e06224233b7e91fc4c83f8830252fe16c9
629 Both of them became irrelevant.
631 .U3 "Backup Prefix
632 .P
633 The backup prefix is the string that was prepended to message
634 filenames to tag them as deleted.
635 By default it had been the comma character `\f(CW,\fP'.
636 In July 2000, Kimmo Suominen introduced
637 the configure option
638 .Sw --with-hash-backup
639 to change the default to the hash symbol `\f(CW#\fP'.
640 The choice was probably personal preference, because first, the
641 option was named
642 .Sw --with-backup-prefix.
643 and had the prefix symbol as argument.
644 But giving the hash symbol as argument caused too many problems
645 for Autoconf,
646 thus the option was limited to use the hash symbol as the default prefix.
647 This supports the assumption, that the choice for the hash was
648 personal preference only.
649 Being related or not, words that start with the hash symbol
650 introduce a comment in the Unix shell.
651 Thus, the command line
652 .Cl "rm #13 #15
653 calls
654 .Pn rm
655 without arguments because the first hash symbol starts the comment
656 that reaches until the end of the line.
657 To delete the backup files,
658 .Cl "rm ./#13 ./#15"
659 needs to be used.
660 Using the hash as backup prefix can be seen as a precaution against
661 data loss.
662 .P
663 I removed the configure option but added the profile entry
664 .Pe backup-prefix ,
665 which allows to specify an arbitrary string as backup prefix.
666 .Ci 6c40d481d661d532dd527eaf34cebb6d3f8ed086
667 Profile entries are the common method to change mmh's behavior.
668 This change did not remove the choice but moved it to a location where
669 it suited better.
670 .P
671 Eventually, however, the new trash folder concept
672 .Cf "Sec. XXX
673 obsoleted the concept of the backup prefix completely.
674 .Ci 8edc5aaf86f9f77124664f6801bc6c6cdf258173
675 .\" (Well, there still are corner-cases to remove until the backup
676 .\" prefix can be laid to rest, eventually.)
677 .\" FIXME: Do this work in the code!
679 .U3 "Editor and Pager
680 .P
681 The two configure options
682 .CW --with-editor=EDITOR
683 .CW --with-pager=PAGER
684 were used to specify the default editor and pager at configure time.
685 Doing so at configure time made sense in the eighties,
686 when the set of available editors and pagers varied much across
687 different systems.
688 Today, the situation is more homogeneous.
689 The programs
690 .Pn vi
691 and
692 .Pn more
693 can be expected to be available on every Unix system,
694 as they are specified by POSIX since two decades.
695 (The specifications for
696 .Pn vi
697 and
698 .Pn more
699 appeared in
700 .[
701 posix 1987
702 .]
703 and,
704 .[
705 posix 1992
706 .]
707 respectively.)
708 As a first step, these two tools were hard-coded as defaults.
709 .Ci 5d43a99db70c12a673028c7758c20cbe3e13ef5f
710 Not changed were the
711 .Pe editor
712 and
713 .Pe moreproc
714 profile entries, which allowed the user to override the system defaults.
715 Later, the concept was reworked to respect the standard environment
716 variables
717 .Ev VISUAL
718 and
719 .Ev PAGER
720 if they are set.
721 Today, mmh determines the editor to use in the following order,
722 taking the first available and non-empty item:
723 .IP (1)
724 Environment variable
725 .Ev MMHEDITOR
726 .IP (2)
727 Profile entry
728 .Pe Editor
729 .IP (3)
730 Environment variable
731 .Ev VISUAL
732 .IP (4)
733 Environment variable
734 .Ev EDITOR
735 .IP (5)
736 Command
737 .Pn vi .
738 .P
739 .Ci f85f4b7ae62e3d05a945dcd46ead51f0a2a89a9b
740 .P
741 The pager to use is determined in a similar order,
742 also taking the first available and non-empty item:
743 .IP (1)
744 Environment variable
745 .Ev MMHPAGER
746 .IP (2)
747 Profile entry
748 .Pe Pager
749 (replaces
750 .Pe moreproc )
751 .IP (3)
752 Environment variable
753 .Ev PAGER
754 .IP (4)
755 Command
756 .Pn more .
757 .P
758 .Ci 0c4214ea2aec6497d0d67b436bbee9bc1d225f1e
759 .P
760 By respecting the
761 .Ev VISUAL /\c
762 .Ev EDITOR
763 and
764 .Ev PAGER
765 environment variables,
766 the new behavior confirms better to the common style on Unix systems.
767 Additionally, the new approach is more uniform and clearer to users.
770 .U3 "ndbm
771 .P
772 .Pn slocal
773 used to depend on
774 .I ndbm ,
775 a database library.
776 The database is used to store the `\fLMessage-ID\fP's of all
777 messages delivered.
778 This enables
779 .Pn slocal
780 to suppress delivering the same message to the same user twice.
781 (This features was enabled by the
782 .Sw -suppressdup
783 switch.)
784 .P
785 A variety of versions of the database library exist.
786 .[
787 wolter unix incompat notes dbm
788 .]
789 Complicated autoconf code was needed to detect them correctly.
790 Further more, the configure switches
791 .Sw --with-ndbm=ARG
792 and
793 .Sw --with-ndbmheader=ARG
794 were added to help with difficult setups that would
795 not be detected automatically or correctly.
796 .P
797 By removing the suppress duplicates feature of
798 .Pn slocal ,
799 the dependency on
800 .I ndbm
801 vanished and 120 lines of complex autoconf code could be saved.
802 .Ci ecd6d6a20cb7a1507e3a20d6c4cb3a1cf14c6bbf
803 The change removed functionality too, but that is minor to the
804 improvement by dropping the dependency and the complex autoconf code.
806 .U3 "mh-e Support
807 .P
808 The configure option
809 .Sw --disable-mhe
810 was removed when the mh-e support was reworked.
811 Mh-e is the Emacs front-end to MH.
812 It requires MH to provide minor additional functions.
813 The
814 .Sw --disable-mhe
815 configure option could switch these extensions off.
816 After removing the support for old versions of mh-e,
817 only the
818 .Sw -build
819 switches of
820 .Pn forw
821 and
822 .Pn repl
823 are left to be mh-e extensions.
824 They are now always built in because they add little code and complexity.
825 In consequence, the
826 .Sw --disable-mhe
827 configure option was removed
828 .Ci a7ce7b4a580d77b6c2c4d980812beb589aa4c643
829 Removing the option removed a second code setup that would have
830 needed to be tested.
831 This change was first done in nmh and thereafter merged into mmh.
832 .P
833 The interface changes in mmh require mh-e to be adjusted in order
834 to be able to use mmh as back-end.
835 This will require minor changes to mh-e, but removing the
836 .Sw -build
837 switches would require more rework.
839 .U3 "Masquerading
840 .P
841 The configure option
842 .Sw --enable-masquerade
843 could take up to three arguments:
844 `draft_from', `mmailid', and `username_extension'.
845 They activated different types of address masquerading.
846 All of them were implemented in the SMTP-speaking
847 .Pn post
848 command, which provided an MSA.
849 Address masquerading is an MTA's task and mmh does not cover
850 this field anymore.
851 Hence, true masquerading needs to be implemented in the external MTA.
852 .P
853 The
854 .I mmailid
855 masquerading type is the oldest one of the three and the only one
856 available in the original MH.
857 It provided a
858 .I username
859 to
860 .I fakeusername
861 mapping, based on the password file's GECOS field.
862 The man page
863 .Mp mh-tailor(5)
864 described the use case as being the following:
865 .QS
866 This is useful if you want the messages you send to always
867 appear to come from the name of an MTA alias rather than your
868 actual account name. For instance, many organizations set up
869 `First.Last' sendmail aliases for all users. If this is
870 the case, the GECOS field for each user should look like:
871 ``First [Middle] Last <First.Last>''
872 .QE
873 .P
874 As mmh sends outgoing mail via the local MTA only,
875 the best location to do such global rewrites is there.
876 Besides, the MTA is conceptionally the right location because it
877 does the reverse mapping for incoming mail (aliasing), too.
878 Further more, masquerading set up there is readily available for all
879 mail software on the system.
880 Hence, mmailid masquerading was removed.
881 .Ci 0836c8000ccb34b59410ef1c15b1b7feac70ce5f
882 .P
883 The
884 .I username_extension
885 masquerading type did not replace the username but would append a suffix,
886 specified by the
887 .Ev USERNAME_EXTENSION
888 environment variable, to it.
889 This provided support for the
890 .I user-extension
891 feature of qmail and the similar
892 .I "plussed user
893 processing of sendmail.
894 The decision to remove this username_extension masquerading was
895 motivated by the fact that
896 .Pn spost
897 hadn't supported it already.
898 .Ci 2abae0bfd0ad5bf898461e50aa4b466d641f23d9
899 Username extensions are possible in mmh, but less convenient to use.
900 .\" XXX format file %(getenv USERNAME_EXTENSION)
901 .P
902 The
903 .I draft_from
904 masquerading type instructed
905 .Pn post
906 to use the value of the
907 .Hd From
908 header field as SMTP envelope sender.
909 Sender addresses could be replaced completely.
910 .Ci b14ea6073f77b4359aaf3fddd0e105989db9
911 Mmh offers a kind of masquerading similar in effect, but
912 with technical differences.
913 As mmh does not transfer messages itself, the local MTA has final control
914 over the sender's address. Any masquerading mmh introduces may be reverted
915 by the MTA.
916 In times of pedantic spam checking, an MTA will take care to use
917 sensible envelope sender addresses to keep its own reputation up.
918 Nonetheless, the MUA can set the
919 .Hd From
920 header field and thereby propose
921 a sender address to the MTA.
922 The MTA may then decide to take that one or generate the canonical sender
923 address for use as envelope sender address.
924 .P
925 In mmh, the MTA will always extract the recipient and sender from the
926 message header (\c
927 .Pn sendmail 's
928 .Sw -t
929 switch).
930 The
931 .Hd From
932 header field of the draft may be set arbitrary by the user.
933 If it is missing, the canonical sender address will be generated by the MTA.
935 .U3 "Remaining Options
936 .P
937 Two configure options remain in mmh.
938 One is the locking method to use:
939 .Sw --with-locking=[dot|fcntl|flock|lockf] .
940 The idea of removing all methods except the portable dot locking
941 and having that one as the default is appealing, but this change
942 requires deeper technical investigation into the topic.
943 The other option,
944 .Sw --enable-debug ,
945 compiles the programs with debugging symbols and does not strip them.
946 This option is likely to stay.
951 .H2 "Command Line Switches
952 .P
953 The command line switches of MH tools follow the X Window style.
954 They are words, introduced by a single dash.
955 For example:
956 .Cl "-truncate" .
957 Every program in mmh has two generic switches:
958 .Sw -help ,
959 to print a short message on how to use the program, and
960 .Sw -Version ,
961 to tell what version of mmh the program belongs to.
962 .P
963 Switches change the behavior of programs.
964 Programs that do one thing in one way require no switches.
965 In most cases, doing something in exactly one way is too limiting.
966 If there is basically one task to accomplish, but it should be done
967 in various ways, switches are a good approach to alter the behavior
968 of a program.
969 Changing the behavior of programs provides flexibility and customization
970 to users, but at the same time it complicates the code, documentation and
971 usage of the program.
972 .\" XXX: Ref
973 Therefore, the number of switches should be kept small.
974 A small set of well-chosen switches does no harm.
975 But usually, the number of switches increases over time.
976 Already in 1985, Rose and Romine have identified this as a major
977 problem of MH:
978 .[ [
979 rose romine real work
980 .], p. 12]
981 .QS
982 A complaint often heard about systems which undergo substantial development
983 by many people over a number of years, is that more and more options are
984 introduced which add little to the functionality but greatly increase the
985 amount of information a user needs to know in order to get useful work done.
986 This is usually referred to as creeping featurism.
987 .QP
988 Unfortunately MH, having undergone six years of off-and-on development by
989 ten or so well-meaning programmers (the present authors included),
990 suffers mightily from this.
991 .QE
992 .P
993 Being reluctant to adding new switches \(en or `options',
994 as Rose and Romine call them \(en is one part of a counter-action,
995 the other part is removing hardly used switches.
996 Nmh's tools had lots of switches already implemented,
997 hence, cleaning up by removing some of them was the more important part
998 of the counter-action.
999 Removing existing functionality is always difficult because it
1000 breaks programs that use these functions.
1001 Also, for every obsolete feature, there'll always be someone who still
1002 uses it and thus opposes its removal.
1003 This puts the developer into the position,
1004 where sensible improvements to style are regarded as destructive acts.
1005 Yet, living with the featurism is far worse, in my eyes, because
1006 future needs will demand adding further features,
1007 worsening the situation more and more.
1008 Rose and Romine added in a footnote,
1009 ``[...]
1010 .Pn send
1011 will no doubt acquire an endless number of switches in the years to come.''
1012 Although clearly humorous, the comment points to the nature of the problem.
1013 Refusing to add any new switches would encounter the problem at its root,
1014 but this is not practical.
1015 New needs will require new switches and it would be unwise to block
1016 them strictly.
1017 Nevertheless, removing obsolete switches still is an effective approach
1018 to deal with the problem.
1019 Working on an experimental branch without an established user base,
1020 eased my work because I did not offend users when I removed existing
1021 functions.
1022 .P
1023 Rose and Romine counted 24 visible and 9 more hidden switches for
1024 .Pn send .
1025 In nmh, they increased up to 32 visible and 12 hidden ones.
1026 At the time of writing, no more than 7 visible switches and 1 hidden switch
1027 have remained in mmh's
1028 .Pn send .
1029 (These numbers include two generic switches, help and version.)
1030 .P
1031 Fig. XXX
1032 .\" XXX Ref
1033 displays the number of switches for each of the tools that is available
1034 in both, nmh and mmh.
1035 The tools are sorted by the number of switches they had in nmh.
1036 Visible and hidden switches were counted,
1037 but not the generic help and version switches.
1038 Whereas in the beginning of the project, the average tool had 11 switches,
1039 now it has no more than 5 \(en only half as many.
1040 If the `no' switches and similar inverse variant are folded onto
1041 their counter-parts, the average tool had 8 switches in pre-mmh times and
1042 has 4 now.
1043 The total number of functional switches in mmh dropped from 465
1044 to 234.
1046 .KS
1047 .in 1c
1048 .so input/switches.grap
1049 .KE
1051 .P
1052 A part of the switches vanished after functions were removed.
1053 This was the case for network mail transfer, for instance.
1054 Sometimes, however, the work flow was the other way:
1055 I looked through the
1056 .Mp mh-chart (7)
1057 man page to identify the tools with apparently too many switches.
1058 Then considering the value of each of the switches by examining
1059 the tool's man page and source code, aided by recherche and testing.
1060 This way, the removal of functions was suggested by the aim to reduce
1061 the number of switches per command.
1064 .U3 "Draft Folder Facility
1065 .P
1066 A change early in the project was the complete transition from
1067 the single draft message to the draft folder facility.
1068 .Ci 337338b404931f06f0db2119c9e145e8ca5a9860
1069 The draft folder facility was introduced in the mid-eighties, when
1070 Rose and Romine called it a ``relatively new feature''.
1071 .[
1072 rose romine real work
1073 .]
1074 Since then, the facility had existed but was inactive by default.
1075 The default activation and the related rework of the tools made it
1076 possible to remove the
1077 .Sw -[no]draftfolder ,
1078 and
1079 .Sw -draftmessage
1080 switches from
1081 .Pn comp ,
1082 .Pn repl ,
1083 .Pn forw ,
1084 .Pn dist ,
1085 .Pn whatnow ,
1086 and
1087 .Pn send .
1088 .Ci 337338b404931f06f0db2119c9e145e8ca5a9860
1089 The only flexibility removed with this change is having multiple
1090 draft folders within one profile.
1091 I consider this a theoretical problem only.
1092 In the same go, the
1093 .Sw -draft
1094 switch of
1095 .Pn anno ,
1096 .Pn refile ,
1097 and
1098 .Pn send
1099 was removed.
1100 The special-casing of `the' draft message became irrelevant after
1101 the rework of the draft system.
1102 (See Sec. XXX.)
1103 Equally,
1104 .Pn comp
1105 lost its
1106 .Sw -file
1107 switch.
1108 The draft folder facility, together with the
1109 .Sw -form
1110 switch, are sufficient.
1113 .U3 "In Place Editing
1114 .P
1115 .Pn anno
1116 had the switches
1117 .Sw -[no]inplace
1118 to either annotate the message in place and thus preserve hard links,
1119 or annotate a copy to replace the original message, breaking hard links.
1120 Following the assumption that linked messages should truly be the
1121 same message, and annotating it should not break the link, the
1122 .Sw -[no]inplace
1123 switches were removed and the previous default
1124 .Sw -inplace
1125 was made the only behavior.
1126 .Ci c8195849d2e366c569271abb0f5f60f4ebf0b4d0
1127 The
1128 .Sw -[no]inplace
1129 switches of
1130 .Pn repl ,
1131 .Pn forw ,
1132 and
1133 .Pn dist
1134 could be removed, too, as they were simply passed through to
1135 .Pn anno .
1136 .P
1137 .Pn burst
1138 also had
1139 .Sw -[no]inplace
1140 switches, but with different meaning.
1141 With
1142 .Sw -inplace ,
1143 the digest had been replaced by the table of contents (i.e. the
1144 introduction text) and the burst messages were placed right
1145 after this message, renumbering all following messages.
1146 Also, any trailing text of the digest was lost, though,
1147 in practice, it usually consists of an end-of-digest marker only.
1148 Nontheless, this behavior appeared less elegant than the
1149 .Sw -noinplace
1150 behavior, which already had been the default.
1151 Nmh's
1152 .Mp burst (1)
1153 man page reads:
1154 .sp \n(PDu
1155 .QS
1156 If -noinplace is given, each digest is preserved, no table
1157 of contents is produced, and the messages contained within
1158 the digest are placed at the end of the folder. Other messages
1159 are not tampered with in any way.
1160 .QE
1161 .LP
1162 The decision to drop the
1163 .Sw -inplace
1164 behavior was supported by the code complexity and the possible data loss
1165 it caused.
1166 .Sw -noinplace
1167 was chosen to be the definitive behavior.
1168 .Ci 68a686adeb39223a5e1ad35e4a24890ec053679d
1171 .U3 "Forms and Format Strings
1172 .P
1173 Historically, the tools that had
1174 .Sw -form
1175 switches to supply a form file had
1176 .Sw -format
1177 switches as well to supply the contents of a form file as a string
1178 on the command line directly.
1179 In consequence, the following two lines equaled:
1180 .VS
1181 scan -form scan.mailx
1182 scan -format "`cat .../scan.mailx`"
1183 VE
1184 The
1185 .Sw -format
1186 switches were dropped in favor for extending the
1187 .Sw -form
1188 switches.
1189 .Ci f51956be123db66b00138f80464d06f030dbb88d
1190 If their argument starts with an equal sign (`='),
1191 then the rest of the argument is taken as a format string,
1192 otherwise the arguments is treated as the name of a format file.
1193 Thus, now the following two lines equal:
1194 .VS
1195 scan -form scan.mailx
1196 scan -form "=`cat .../scan.mailx`"
1197 VE
1198 This rework removed the prefix collision between
1199 .Sw -form
1200 and
1201 .Sw -format .
1202 Now, typing
1203 .Sw -fo
1204 suffices to specify form or format string.
1205 .P
1206 The different meaning of
1207 .Sw -format
1208 for
1209 .Pn repl
1210 and
1211 .Pn forw
1212 was removed in mmh.
1213 .Pn forw
1214 was completely switched to MIME-type forwarding, thus removing the
1215 .Sw -[no]format .
1216 .Ci 6e271608b7b9c23771523f88d23a4d3593010cf1
1217 For
1218 .Pn repl ,
1219 the
1220 .Sw -[no]format
1221 switches were reworked to
1222 .Sw -[no]filter
1223 switches.
1224 .Ci 67411b1f95d6ec987b4c732459e1ba8a8ac192c6
1225 The
1226 .Sw -format
1227 switches of
1228 .Pn send
1229 and
1230 .Pn post ,
1231 which had a third meaning,
1232 were removed likewise.
1233 .Ci f3cb7cde0e6f10451b6848678d95860d512224b9
1234 Eventually, the ambiguity of the
1235 .Sw -format
1236 switches was resolved by not anymore having any such switch in mmh.
1239 .U3 "MIME Tools
1240 .P
1241 The MIME tools, which were once part of
1242 .Pn mhn
1243 [sic!],
1244 had several switches that added little practical value to the programs.
1245 The
1246 .Sw -[no]realsize
1247 switches of
1248 .Pn mhbuild
1249 and
1250 .Pn mhlist
1251 were removed, doing real size calculations always now
1252 .Ci 8d8f1c3abc586c005c904e52c4adbfe694d2201c ,
1253 as
1254 ``This provides an accurate count at the expense of a small delay.''
1255 This small delay is not noticable on modern systems.
1256 .P
1257 The
1258 .Sw -[no]check
1259 switches were removed together with the support for
1260 .Hd Content-MD5
1261 header fields.
1262 .[
1263 rfc 1864
1264 .]
1265 .Ci 31dc797eb5178970d68962ca8939da3fd9a8efda
1266 (See Sec. XXX)
1267 .P
1268 The
1269 .Sw -[no]ebcdicsafe
1270 and
1271 .Sw -[no]rfc934mode
1272 switches of
1273 .Pn mhbuild
1274 were removed because they are considered obsolete.
1275 .Ci 01a3480928da485b4d6109d36d751dfa71799d58
1276 .Ci 3363e2624dce0eb8164cf8b3f1ab385c8ff72e88
1277 .P
1278 Content caching of external MIME parts, activated with the
1279 .Sw -rcache
1280 and
1281 .Sw -wcache
1282 switches was completely removed.
1283 .Ci d1fefd9f614e4dc3cda16da6c69133c1b2005269
1284 External MIME parts are rare today, having a caching facility
1285 for them is appears to be unnecessary.
1286 .P
1287 In pre-MIME times,
1288 .Pn mhl
1289 had covered many tasks that are part of MIME handling today.
1290 Therefore,
1291 .Pn mhl
1292 could be simplified to a large extend, reducing the number of its
1293 switches from 21 to 6.
1294 .Ci 350ad6d3542a07639213cf2a4fe524e829c1e7b6
1295 .Ci 0e46503be3c855bddaeae3843e1b659279c35d70
1298 .U3 "Mail Transfer Switches
1299 .P
1300 With the removal of the mail transfer facilities, a lot of switches
1301 vanished automatically.
1302 .Pn inc
1303 lost 9 switches, namely
1304 .Sw -host ,
1305 .Sw -port ,
1306 .Sw -user ,
1307 .Sw -proxy ,
1308 .Sw -snoop ,
1309 .Sw -[no]pack ,
1310 as well as
1311 .Sw -sasl
1312 and
1313 .Sw -saslmech .
1314 .Pn send
1315 and
1316 .Pn post
1317 lost 11 switches each, namely
1318 .Sw -server ,
1319 .Sw -port ,
1320 .Sw -client ,
1321 .Sw -user ,
1322 .Sw -mail ,
1323 .Sw -saml ,
1324 .Sw -send ,
1325 .Sw -soml ,
1326 .Sw -snoop ,
1327 as well as
1328 .Sw -sasl ,
1329 .Sw -saslmech ,
1330 and
1331 .Sw -tls .
1332 .Pn send
1333 had the switches only to pass them further to
1334 .Pn post ,
1335 because the user would invoke
1336 .Pn post
1337 not directly, but through
1338 .Pn send .
1339 All these switches, except
1340 .Sw -snoop
1341 were usually defined as default switches in the user's profile,
1342 but hardly given in interactive usage.
1343 .P
1344 Of course, those switches did not really ``vanish'', but the configuration
1345 they did was handed over to external MSAs and MRAs.
1346 Instead of setting up the mail transfer in mmh, it is set up in
1347 external tools.
1348 Yet, this simplifies mmh.
1349 Specialized external tools will likely have simple configuration files.
1350 Hence, instead of having one complicated central configuration file,
1351 the configuration of each domain is separate.
1352 Although the user needs to learn to configure each of the tools,
1353 each configuration is likely much simpler.
1356 .U3 "Maildrop Formats
1357 .P
1358 With the removal of MMDF maildrop format support,
1359 .Pn packf
1360 and
1361 .Pn rcvpack
1362 no longer needed their
1363 .Sw -mbox
1364 and
1365 .Sw -mmdf
1366 switches.
1367 .Sw -mbox
1368 is the sole behavior now.
1369 .Ci 3916ab66ad5d183705ac12357621ea8661afd3c0
1370 In the same go,
1371 .Pn packf
1372 and
1373 .Pn rcvpack
1374 were reworked (see Sec. XXX) and their
1375 .Sw -file
1376 switch became unnecessary.
1377 .Ci ca1023716d4c2ab890696f3e41fa0d94267a940e
1380 .U3 "Terminal Magic
1381 .P
1382 Mmh's tools will no longer clear the screen (\c
1383 .Pn scan 's
1384 and
1385 .Pn mhl 's
1386 .Sw -[no]clear
1387 switches
1388 .Ci e57b17343dcb3ff373ef4dd089fbe778f0c7c270
1389 .Ci 943765e7ac5693ae177fd8d2b5a2440e53ce816e ).
1390 Neither will
1391 .Pn mhl
1392 ring the bell (\c
1393 .Sw -[no]bell
1394 .Ci e11983f44e59d8de236affa5b0d0d3067c192e24 )
1395 nor page the output itself (\c
1396 .Sw -length
1397 .Ci 5b9d883db0318ed2b84bb82dee880d7381f99188 ).
1398 .P
1399 Generally, the pager to use is no longer specified with the
1400 .Sw -[no]moreproc
1401 command line switches for
1402 .Pn mhl
1403 and
1404 .Pn show /\c
1405 .Pn mhshow .
1406 .Ci 39e87a75b5c2d3572ec72e717720b44af291e88a
1407 .P
1408 .Pn prompter
1409 lost its
1410 .Sw -erase
1411 and
1412 .Sw -kill
1413 switches because today the terminal cares for the line editing keys.
1416 .U3 "Header Printing
1417 .P
1418 .Pn folder 's
1419 data output is self-explaining enough that
1420 displaying the header line makes few sense.
1421 Hence, the
1422 .Sw -[no]header
1423 switch was removed and headers are never printed.
1424 .Ci 601cc73d1fa05ce96faa728f036d6c51b91701c7
1425 .P
1426 In
1427 .Pn mhlist ,
1428 the
1429 .Sw -[no]header
1430 switches were removed, too.
1431 .Ci b24f96523aaf60e44e04a3ffb1d22e69a13a602f
1432 But in this case headers are always printed,
1433 because the output is not self-explaining.
1434 .P
1435 .Pn scan
1436 also had
1437 .Sw -[no]header
1438 switches.
1439 Printing the header had been sensible until the introduction of
1440 format strings made it impossible to display the column headings.
1441 Only the folder name and the current date remained to be printed.
1442 As this information can be perfectly retrieved by
1443 .Pn folder
1444 and
1445 .Pn date ,
1446 consequently, the switches were removed.
1447 .Ci c477dc5d1d03fa6d9a8ab3dd3508c63cbddc044e
1448 .P
1449 By removing all
1450 .Sw -header
1451 switches, the collision with
1452 .Sw -help
1453 on the first two letters was resolved.
1454 Currently,
1455 .Sw -h
1456 evaluates to
1457 .Sw -help
1458 for all tools of mmh.
1461 .U3 "Suppressing Edits or the WhatNow Shell
1462 .P
1463 The
1464 .Sw -noedit
1465 switch of
1466 .Pn comp ,
1467 .Pn repl ,
1468 .Pn forw ,
1469 .Pn dist ,
1470 and
1471 .Pn whatnow
1472 was removed, but it can now be replaced by specifying
1473 .Sw -editor
1474 with an empty argument.
1475 .Ci 75fca31a5b9d5c1a99c74ab14c94438d8852fba9
1476 (Specifying
1477 .Cl "-editor true
1478 is nearly the same, only differing by the previous editor being set.)
1479 .P
1480 The more important change is the removal of the
1481 .Sw -nowhatnowproc
1482 switch.
1483 .Ci ee4f43cf2ef0084ec698e4e87159a94c01940622
1484 This switch had introduced an awkward behavior, as explained in nmh's
1485 man page for
1486 .Mp comp (1):
1487 .QS
1488 The \-editor editor switch indicates the editor to use for
1489 the initial edit. Upon exiting from the editor, comp will
1490 invoke the whatnow program. See whatnow(1) for a discussion
1491 of available options. The invocation of this program can be
1492 inhibited by using the \-nowhatnowproc switch. (In truth of
1493 fact, it is the whatnow program which starts the initial
1494 edit. Hence, \-nowhatnowproc will prevent any edit from
1495 occurring.)
1496 .QE
1497 .P
1498 Effectively, the
1499 .Sw -nowhatnowproc
1500 switch creates only a draft message.
1501 As
1502 .Cl "-whatnowproc true
1503 causes the same behavior, the
1504 .Sw -nowhatnowproc
1505 switch was removed for being redundant.
1506 Likely, the
1507 .Sw -nowhatnowproc
1508 switch was intended to be used by front-ends.
1511 .U3 "Compatibility Switches
1512 .BU
1513 The hidden
1514 .Sw -[no]total
1515 switches of
1516 .Pn flist .
1517 They were simply the inverse of the visible
1518 .Sw -[no]fast
1519 switches:
1520 .Sw -total
1521 was
1522 .Sw -nofast
1523 and
1524 .Sw -nototal
1525 was
1526 .Sw -fast .
1527 I removed the
1528 .Sw -[no]total
1529 legacy.
1530 .Ci ea21fe2c4bd23c639bef251398fae809875732ec
1531 .BU
1532 The
1533 .Sw -subject
1534 switch of
1535 .Pn sortm
1536 existed for compatibility only.
1537 It can be fully replaced by
1538 .Cl "-textfield subject
1539 thus it was removed.
1540 .Ci 00140a3c86e9def69d98ba2ffd4d6e50ef6326ea
1543 .U3 "Various
1544 .BU
1545 In order to avoid prefix collisions among switch names, the
1546 .Sw -version
1547 switch was renamed to
1548 .Sw -Version
1549 (with capital `V').
1550 .Ci 32b2354dbaf4bf934936eb5b102a4a3d2fdd209a
1551 Every program has the
1552 .Sw -version
1553 switch but its first three letters collided with the
1554 .Sw -verbose
1555 switch, present in many programs.
1556 The rename solved this problem once for all.
1557 Although this rename breaks a basic interface, having the
1558 .Sw -V
1559 abbreviation to display the version information, isn't all too bad.
1560 .BU
1561 .Sw -[no]preserve
1562 of
1563 .Pn refile
1564 was removed because what use was it anyway?
1565 .QS
1566 Normally when a message is refiled, for each destination
1567 folder it is assigned the number which is one above the current
1568 highest message number in that folder. Use of the
1569 \-preserv [sic!] switch will override this message renaming, and try
1570 to preserve the number of the message. If a conflict for a
1571 particular folder occurs when using the \-preserve switch,
1572 then refile will use the next available message number which
1573 is above the message number you wish to preserve.
1574 .QE
1575 .BU
1576 The removal of the
1577 .Sw -[no]reverse
1578 switches of
1579 .Pn scan
1580 .Ci 8edc5aaf86f9f77124664f6801bc6c6cdf258173
1581 is a bug fix, supported by the comments
1582 ``\-[no]reverse under #ifdef BERK (I really HATE this)''
1583 by Rose and
1584 ``Lists messages in reverse order with the `\-reverse' switch.
1585 This should be considered a bug.'' by Romine in the documentation.
1586 The question remains why neither Rose and Romine had fixed this
1587 bug in the eighties when they wrote these comments nor has anyone
1588 thereafter.
1591 .ig
1593 forw: [no]dashstuffing(mhl)
1595 mhshow: [no]pause [no]serialonly
1597 mhmail: resent queued
1598 inc: snoop, (pop)
1600 mhl: [no]faceproc folder sleep
1601 [no]dashstuffing(forw) digest list volume number issue number
1603 prompter: [no]doteof
1605 refile: [no]preserve [no]unlink [no]rmmproc
1607 send: [no]forward [no]mime [no]msgid
1608 [no]push split [no]unique (sasl) width snoop [no]dashstuffing
1609 attach attachformat
1610 whatnow: (noedit) attach
1612 slocal: [no]suppressdups
1614 spost: [no]filter [no]backup width [no]push idanno
1615 [no]check(whom) whom(whom)
1617 whom: ???
1619 ..
1622 .ig
1624 .P
1625 In the best case, all switches are unambiguous on the first character,
1626 or on the three-letter prefix for the `no' variants.
1627 Reducing switch prefix collisions, shortens the necessary prefix length
1628 the user must type.
1629 Having less switches helps best.
1631 ..
1634 .\" XXX: whatnow prompt commands
1639 .H1 "Modernizing
1640 .P
1641 In the over thirty years of MH's existence, its code base was
1642 extended more and more.
1643 New features entered the project and became alternatives to the
1644 existing behavior.
1645 Relicts from several decades have gathered in the code base,
1646 but seldom obsolete features were dropped.
1647 This section describes the removing of old code
1648 and the modernizing of the default setup.
1649 It focuses on the functional aspect only;
1650 the non-functional aspects of code style are discussed in
1651 .\" FIXME REF
1652 Sec. XXX.
1655 .H2 "Code Relicts
1656 .P
1657 My position to drop obsolete functions of mmh, in order to remove old code,
1658 is much more revolutional than the nmh community likes to have it.
1659 Working on an experimental version, I was able to quickly drop
1660 functionality I considered ancient.
1661 The need for consensus with peers would have slowed this process down.
1662 Without the need to justify my decisions, I was able to rush forward.
1663 In December 2011, Paul Vixie motivated the nmh developers to just
1664 do the work:
1665 .[
1666 paul vixie edginess nmh-workers
1667 .]
1668 .QS
1669 let's stop walking on egg shells with this code base. there's no need to
1670 discuss whether to keep using vfork, just note in [sic!] passing, [...]
1671 we don't need a separate branch for removing vmh
1672 or ridding ourselves of #ifdef's or removing posix replacement functions
1673 or depending on pure ansi/posix "libc".
1674 .QP
1675 these things should each be a day or two of work and the "main branch"
1676 should just be modern. [...]
1677 let's push forward, aggressively.
1678 .QE
1679 .LP
1680 I did so already in the months before.
1681 I pushed forward.
1682 I simply dropped the cruft.
1683 .P
1684 The decision to drop a feature was based on literature research and
1685 careful thinking, but whether having had contact to this particular
1686 feature within my own computer life served as a rule of thumb.
1687 Always, I explained my reasons in the commit messages
1688 in the version control system.
1689 Hence, others can comprehend my view and argue for undoing the change
1690 if I have missed an important aspect.
1691 I was quick in dropping parts.
1692 I rather re-included falsely dropped parts than going a slower pace.
1693 Mmh is experimental work; it required tough decisions.
1696 .U3 "Forking
1697 .P
1698 Being a tool chest, MH creates many processes.
1699 In earlier times
1700 .Fu fork()
1701 had been an expensive system call, because the process's image needed
1702 to be duplicated completely at once.
1703 This was especially painful in the common case when the image gets
1704 replaced by a call to
1705 .Fu exec()
1706 right after having forked the child process.
1707 The
1708 .Fu vfork()
1709 system call was invented to speed up this particular case.
1710 It completely omits the duplication of the image.
1711 On old systems this resulted in significant speed ups.
1712 Therefore MH used
1713 .Fu vfork()
1714 whenever possible.
1715 .P
1716 Modern memory management units support copy-on-write semantics, which make
1717 .Fu fork()
1718 almost as fast as
1719 .Fu vfork() .
1720 The man page of
1721 .Mp vfork (2)
1722 in FreeBSD 8.0 states:
1723 .QS
1724 This system call will be eliminated when proper system sharing mechanisms
1725 are implemented. Users should not depend on the memory sharing semantics
1726 of vfork() as it will, in that case, be made synonymous to fork(2).
1727 .QE
1728 .LP
1729 Vixie supports the removal with the note that ``the last
1730 system on which fork was so slow that an mh user would notice it, was
1731 Eunice. that was 1987''.
1732 .[
1733 nmh-workers vixie edginess
1734 .]
1735 I replaced all calls to
1736 .Fu vfork()
1737 with calls to
1738 .Fu fork() .
1739 .Ci 40821f5c1316e9205a08375e7075909cc9968e7d
1740 .P
1741 Related to the costs of
1742 .Fu fork()
1743 is the probability of its success.
1744 In the eighties, on heavy loaded systems, calls to
1745 .Fu fork()
1746 were prone to failure.
1747 Hence, many of the
1748 .Fu fork()
1749 calls in the code were wrapped into loops to retry the
1750 .Fu fork()
1751 several times, to increase the changes to succeed, eventually.
1752 On modern systems, a failing
1753 .Fu fork()
1754 call is unusual.
1755 Hence, in the rare case when
1756 .Fu fork()
1757 fails, mmh programs simply abort.
1758 .Ci 5fbf37ee68e018998ada61eeab73e035b26834b6
1761 .U3 "Header Fields
1762 .BU
1763 The
1764 .Hd Encrypted
1765 header field was introduced by RFC\|822,
1766 but already marked as legacy in RFC\|2822.
1767 Today, OpenPGP provides the basis for standardized exchange of encrypted
1768 messages [RFC\|4880, RFC\|3156].
1769 Hence, the support for
1770 .Hd Encrypted
1771 header fields is removed in mmh.
1772 .Ci 064527f7b57ab050e5af13e15ad99aeeab125857
1773 .BU
1774 Native support for
1775 .Hd Face
1776 header fields has been removed, as well.
1777 .Ci 8e5be81f784682822f5e868c1bf3c8624682bd23
1778 This feature is similar to the
1779 .Hd X-Face
1780 header field in its intent,
1781 but takes a different approach to store the image.
1782 Instead of encoding the image data directly into the header field,
1783 it contains the hostname and UDP port where the image
1784 date can be retrieved.
1785 There exists even a third Face system,
1786 which is the successor of
1787 .Hd X-Face ,
1788 although it re-uses the
1789 .Hd Face
1790 header field.
1791 It was invented in 2005 and supports colored PNG images.
1792 None of the Face systems described here is popular today.
1793 Hence, mmh has no direct support for them.
1794 .BU
1795 The
1796 .Hd Content-MD5
1797 header field was introduced by RFC\|1864.
1798 It provides detection of data corruption during the transfer.
1799 But it can not ensure verbatim end-to-end delivery of the contents
1800 [RFC\|1864].
1801 The proper approach to verify content integrity in an
1802 end-to-end relationship is the use of digital cryptography.
1803 .\" XXX (RFCs FIXME).
1804 On the other hand, transfer protocols should detect corruption during
1805 the transmission.
1806 The TCP includes a checksum field therefore.
1807 These two approaches in combinations render the
1808 .Hd Content-MD5
1809 header field superfluous.
1810 Not a single one out of 4\|200 messages from two decades
1811 in an nmh-workers mailing list archive contains a
1812 .Hd Content-MD5
1813 header field.
1814 Neither did any of the 60\|000 messages in my personal mail storage.
1815 Removing the support for this header field,
1816 removed the last place where MD5 computation was needed.
1817 .Ci 31dc797eb5178970d68962ca8939da3fd9a8efda
1818 Hence, the MD5 code could be removed as well.
1819 Over 500 lines of code vanished by this one change.
1822 .U3 "MMDF maildrop support
1823 .P
1824 This type of format is conceptionally similar to the mbox format,
1825 but uses a different message delimiter (`\fL^A^A^A^A\fP' instead of
1826 `\fLFrom\0\fP').
1827 Mbox is the de-facto standard maildrop format on Unix,
1828 whereas the MMDF maildrop format became forgotten.
1829 I did drop MMDF maildrop format support.
1830 Mbox is the only packed mailbox format supported in mmh.
1831 .P
1832 The simplifications within the code were moderate.
1833 Mainly, the reading and writing of MMDF mailbox files was removed.
1834 But also, switches of
1835 .Pn packf
1836 and
1837 .Pn rcvpack
1838 could be removed.
1839 .Ci 3916ab66ad5d183705ac12357621ea8661afd3c0
1840 In the message parsing function
1841 .Fn sbr/m_getfld.c ,
1842 knowledge of MMDF packed mail boxes was removed.
1843 .Ci 684ec30d81e1223a282764452f4902ed4ad1c754
1844 Further code structure simplifications may be possible there,
1845 because only one single packed mailbox format is left to be supported.
1846 I have not worked on them yet because
1847 .Fu m_getfld()
1848 is heavily optimized and thus dangerous to touch.
1849 The risk of damaging the intricate workings of the optimized code is
1850 too high.
1851 .\" XXX: move somewhere else
1852 This problem is know to the developers of nmh, too.
1853 They also avoid touching this minefield.
1856 .U3 "Prompter's Control Keys
1857 .P
1858 The program
1859 .Pn prompter
1860 queries the user to fill in a message form.
1861 When used by
1862 .Pn comp
1863 as
1864 .Cl "comp -editor prompter" ,
1865 the resulting behavior is similar to
1866 .Pn mailx .
1867 Apparently,
1868 .Pn prompter
1869 hadn't been touched lately.
1870 Otherwise it's hardly explainable why it
1871 still offered the switches
1872 .Sw -erase
1873 .Ar chr
1874 and
1875 .Sw -kill
1876 .Ar chr
1877 to name the characters for command line editing.
1878 The times when this had been necessary are long time gone.
1879 Today these things work out-of-the-box, and if not, are configured
1880 with the standard tool
1881 .Pn stty .
1882 The switches are removed now
1883 .Ci 0bd9750710cdbab80cfb4036dd87af20afe1552f .
1886 .U3 "Hardcopy Terminal Support
1887 .P
1888 More of a funny anecdote is a check for being connected to a
1889 hardcopy terminal.
1890 It remained in the code until Spring 2012, when I finally removed it
1891 .Ci b7764c4a6b71d37918a97594d866258f154017ca .
1892 I would be truly happy to see such a terminal in action today,
1893 maybe even being able to work on it.
1894 But I fear my chances are null.
1895 .P
1896 The check only prevented a pager to be placed between the printing
1897 program (\c
1898 .Pn mhl )
1899 and the terminal.
1900 In nmh, this could have been ensured statically with the
1901 .Sw -nomoreproc
1902 at the command line, too.
1903 In mmh, setting the profile entry
1904 .Pe Pager
1905 or the environment variable
1906 .Ev PAGER
1907 to
1908 .Pn cat
1909 does the job.
1914 .H2 "Attachments
1915 .P
1916 The mind model of email attachments is unrelated to MIME.
1917 Although the MIME RFCs (2045 through 2049) define the technical
1918 requirements for having attachments, they do not mention the word
1919 ``attachment''.
1920 Instead of attachments, MIME talks about ``multi-part message bodies''
1921 [RFC\|2045], a more general concept.
1922 Multi-part messages are messages
1923 ``in which one or more different
1924 sets of data are combined in a single body''
1925 [RFC\|2046].
1926 MIME keeps its descriptions generic;
1927 it does not imply specific usage models.
1928 One usage model became prevalent: attachments.
1929 The idea is having a main text document with files of arbitrary kind
1930 attached to it.
1931 In MIME terms, this is a multi-part message having a text part first
1932 and parts of arbitrary type following.
1933 .P
1934 MH's MIME support is a direct implementation of the RFCs.
1935 The perception of the topic described in the RFCs is clearly visible
1936 in MH's implementation.
1937 In result, MH had all the MIME features but no idea of attachments.
1938 But users don't need all the MIME features,
1939 they want convenient attachment handling.
1942 .U3 "Composing MIME Messages
1943 .P
1944 In order to improve the situation on the message composing side,
1945 Jon Steinhart had added an attachment system to nmh in 2002.
1946 .Ci 7480dbc14bc90f2d872d434205c0784704213252
1947 In the file
1948 .Fn docs/README-ATTACHMENTS ,
1949 he described his motivation to do so as such:
1950 .QS
1951 Although nmh contains the necessary functionality for MIME message handing,
1952 the interface to this functionality is pretty obtuse.
1953 There's no way that I'm ever going to convince my partner to write
1954 .Pn mhbuild
1955 composition files!
1956 .QE
1957 .LP
1958 With this change, the mind model of attachments entered nmh.
1959 In the same document:
1960 .QS
1961 These changes simplify the task of managing attachments on draft files.
1962 They allow attachments to be added, listed, and deleted.
1963 MIME messages are automatically created when drafts with attachments
1964 are sent.
1965 .QE
1966 .LP
1967 Unfortunately, the attachment system,
1968 like any new facilities in nmh,
1969 was inactive by default.
1970 .P
1971 During my work in Argentina, I tried to improve the attachment system.
1972 But, because of great opposition in the nmh community,
1973 my patch died as a proposal on the mailing list, after long discussions.
1974 .[
1975 nmh-workers attachment proposal
1976 .]
1977 In January 2012, I extended the patch and applied it to mmh.
1978 .Ci 8ff284ff9167eff8f5349481529332d59ed913b1
1979 In mmh, the attachment system is active by default.
1980 Instead of command line switches, the
1981 .Pe Attachment-Header
1982 profile entry is used to specify
1983 the name of the attachment header field.
1984 It is pre-defined to
1985 .Hd Attach .
1986 .P
1987 To add an attachment to a draft, simply add an attachment header:
1988 .VS
1989 To: bob
1990 Subject: The file you wanted
1991 Attach: /path/to/the/file-bob-wanted
1992 --------
1993 Here it is.
1994 VE
1995 The header field can be added to the draft manually in the editor,
1996 or by using the `attach' command at the WhatNow prompt, or
1997 non-interactively with
1998 .Pn anno :
1999 .VS
2000 anno -append -nodate -component Attach -text /path/to/attachment
2001 VE
2002 Drafts with attachment headers are converted to MIME automatically by
2003 .Pn send .
2004 The conversion to MIME is invisible to the user.
2005 The draft stored in the draft folder is always in source form, with
2006 attachment headers.
2007 If the MIMEification fails, for instance because the file to attach
2008 is not accessible, the original draft is not changed.
2009 .P
2010 The attachment system handles the forwarding of messages, too.
2011 If the attachment header value starts with a plus character (`+'),
2012 like in
2013 .Cl "Attach: +bob 30 42" ,
2014 The given messages in the specified folder will be attached.
2015 This allowed to simplify
2016 .Pn forw .
2017 .Ci f41f04cf4ceca7355232cf7413e59afafccc9550
2018 .P
2019 Closely related to attachments is non-ASCII text content,
2020 because it requires MIME too.
2021 In nmh, the user needed to call `mime' at the WhatNow prompt
2022 to have the draft converted to MIME.
2023 This was necessary whenever the draft contained non-ASCII characters.
2024 If the user did not call `mime', a broken message would be sent.
2025 Therefore, the
2026 .Pe automimeproc
2027 profile entry could be specified to have the `mime' command invoked
2028 automatically each time.
2029 Unfortunately, this approach conflicted with with attachment system
2030 because the draft would already be in MIME format at the time
2031 when the attachment system wanted to MIMEify it.
2032 To use nmh's attachment system, `mime' must not be called at the
2033 WhatNow prompt and
2034 .Pe automimeproc
2035 must not be set in the profile.
2036 But then the case of non-ASCII text without attachment headers was
2037 not caught.
2038 All in all, the solution was complex and irritating.
2039 My patch from December 2010 would have simplified the situation.
2040 .P
2041 Mmh's current solution is even more elaborate.
2042 Any necessary MIMEification is done automatically.
2043 There is no `mime' command at the WhatNow prompt anymore.
2044 The draft will be converted automatically to MIME when either an
2045 attachment header or non-ASCII text is present.
2046 Further more, the special meaning of the hash character (`#')
2047 at line beginnings in the draft message is removed.
2048 Users need not at all deal with the whole topic.
2049 .P
2050 Although the new approach does not anymore support arbitrary MIME
2051 compositions directly, the full power of
2052 .Pn mhbuild
2053 can still be accessed.
2054 Given no attachment headers are included, the user can create
2055 .Pn mhbuild
2056 composition drafts like in nmh.
2057 Then, at the WhatNow prompt, he needs to invoke
2058 .Cl "edit mhbuild
2059 to convert it to MIME.
2060 Because the resulting draft does neither contain non-ASCII characters
2061 nor has it attachment headers, the attachment system will not touch it.
2062 .P
2063 The approach taken in mmh is tailored towards todays most common case:
2064 a text part with possibly attachments.
2065 This case is simplified a lot for users.
2068 .U3 "MIME Type Guessing
2069 .P
2070 The use of
2071 .Pn mhbuild
2072 composition drafts had one notable advantage over attachment headers
2073 from the programmer's point of view: The user provides the appropriate
2074 MIME types for files to include.
2075 The attachment system needs to find out the correct MIME type itself.
2076 This is a difficult task, yet it spares the user irritating work.
2077 Determining the correct MIME type of content is partly mechanical,
2078 partly intelligent work.
2079 Forcing the user to find out the correct MIME type,
2080 forces him to do partly mechanical work.
2081 Letting the computer do the work, can lead to bad choices for difficult
2082 content.
2083 For mmh, the latter option was chosen.
2084 .P
2085 Determining the MIME type by the suffix of the file name is a dumb
2086 approach, yet it is simple to implement and provides good results
2087 for the common cases.
2088 Mmh implements this approach in the
2089 .Pn print-mimetype
2090 script.
2091 .Ci 4b5944268ea0da7bb30598a27857304758ea9b44
2092 Using it is the default choice.
2093 .P
2094 A far better, though less portable, approach is the use of
2095 .Pn file .
2096 This standard tool tries to determine the type of files.
2097 Unfortunately, its capabilities and accuracy varies from system to system.
2098 Additionally, its output was only intended for human beings,
2099 but not to be used by programs.
2100 It varies much.
2101 Nevertheless, modern versions of GNU
2102 .Pn file ,
2103 which is prevalent on the popular GNU/Linux systems,
2104 provides MIME type output in machine-readable form.
2105 Although this solution is highly system-dependent,
2106 it solves the difficult problem well.
2107 On systems where GNU
2108 .Pn file ,
2109 version 5.04 or higher, is available it should be used.
2110 One needs to specify the following profile entry to do so:
2111 .Ci 3baec236a39c5c89a9bda8dbd988d643a21decc6
2112 .VS
2113 Mime-Type-Query: file -b --mime
2114 VE
2115 .LP
2116 Other versions of
2117 .Pn file
2118 might possibly be usable with wrapper scripts to reformat the output.
2119 The diversity among
2120 .Pn file
2121 implementations is great; one needs to check the local variant.
2122 .P
2123 If no MIME type can be determined, text content gets sent as
2124 `text/plain' and anything else under the generic fall-back type
2125 `application/octet-stream'.
2126 It is not possible in mmh to override the automatic MIME type guessing
2127 for a specific file.
2128 To do so, the user would need to know in advance for which file
2129 the automatic guessing does fail, or the system would require interaction.
2130 I consider both cases impractical.
2131 The existing solution should be sufficient.
2132 If not, the user may always fall back to
2133 .Pn mhbuild
2134 composition drafts and ignore the attachment system.
2137 .U3 "Storing Attachments
2138 .P
2139 Extracting MIME parts of a message and storing them to disk is done by
2140 .Pn mhstore .
2141 The program has two operation modes,
2142 .Sw -auto
2143 and
2144 .Sw -noauto .
2145 With the former one, each part is stored under the filename given in the
2146 MIME part's meta information, if available.
2147 This naming information is usually available for modern attachments.
2148 If no filename is available, this MIME part is stored as if
2149 .Sw -noauto
2150 would have been specified.
2151 In the
2152 .Sw -noauto
2153 mode, the parts are processed according to rules, defined by
2154 .Pe mhstore-store-*
2155 profile entries.
2156 These rules define generic filename templates for storing
2157 or commands to post-process the contents in arbitrary ways.
2158 If no matching rule is available the part is stored under a generic
2159 filename, built from message number, MIME part number, and MIME type.
2160 .P
2161 The
2162 .Sw -noauto
2163 mode had been the default in nmh because it was considered safe,
2164 in contrast to the
2165 .Sw -auto
2166 mode.
2167 In mmh,
2168 .Sw -auto
2169 is not dangerous anymore.
2170 Two changes were necessary:
2171 .BU
2172 Any directory path is removed from the proposed filename.
2173 Thus, the files are always stored in the expected directory.
2174 .Ci 41b6eadbcecf63c9a66aa5e582011987494abefb
2175 .BU
2176 Tar files are not extracted automatically any more.
2177 Thus, the rest of the file system will not be touched.
2178 .Ci 94c80042eae3383c812d9552089953f9846b1bb6
2179 .LP
2180 Now, the outcome of mmh's
2181 .Cl "mhstore -auto
2182 can be foreseen from the output of
2183 .Cl "mhlist -verbose" .
2184 .P
2185 The
2186 .Sw -noauto
2187 mode is seen to be more powerful but less convenient.
2188 On the other hand,
2189 .Sw -auto
2190 is safe now and
2191 storing attachments under their original name is intuitive.
2192 Hence,
2193 .Sw -auto
2194 serves better as the default option.
2195 .Ci 3410b680416c49a7617491af38bc1929855a331d
2196 .P
2197 Files are stored into the directory given by the
2198 .Pe Nmh-Storage
2199 profile entry, if set, or
2200 into the current working directory, otherwise.
2201 Storing to different directories is only possible with
2202 .Pe mhstore-store-*
2203 profile entries.
2204 .P
2205 Still, in both modes, existing files get overwritten silently.
2206 This can be considered a bug.
2207 Yet, each other behavior has its draw-backs, too.
2208 Refusing to replace files requires adding a
2209 .Sw -force
2210 option.
2211 Users will likely need to invoke
2212 .Pn mhstore
2213 a second time with
2214 .Sw -force
2215 then.
2216 Eventually, only the user can decide in the concrete case.
2217 This requires interaction, which I like to avoid if possible.
2218 Appending a unique suffix to the filename is another bad option.
2219 For now, the behavior remains as it is.
2220 .P
2221 In mmh, only MIME parts of type message are special in
2222 .Pn mhstore 's
2223 .Sw -auto
2224 mode.
2225 Instead of storing message/rfc822 parts as files to disk,
2226 they are stored as messages into the current mail folder.
2227 The same applies to message/partial, only, the parts are reassembled
2228 automatically before.
2229 Parts of type message/external-body are not automatically retrieved
2230 anymore. Instead, Information on how to retrieve them is output.
2231 Not supporting this rare case saved nearly one thousand lines of code.
2232 .Ci 55e1d8c654ee0f7c45b9361ce34617983b454c32
2233 .\" XXX mention somewhere else too: (The profile entry `nmh-access-ftp'
2234 .\" and sbr/ruserpass.c for reading ~/.netrc are gone now.)
2235 Not special anymore is `application/octet-stream; type=tar'.
2236 Automatically extracting such MIME parts had been the dangerous part
2237 of the
2238 .Sw -auto
2239 mode.
2240 .Ci 94c80042eae3383c812d9552089953f9846b1bb6
2244 .U3 "Showing MIME Messages
2245 .P
2246 The program
2247 .Pn mhshow
2248 had been written to display MIME messages.
2249 It implemented the conceptional view of the MIME RFCs.
2250 Nmh's
2251 .Pn mhshow
2252 handled each MIME part independently, presenting them separately
2253 to the user.
2254 This does not match today's understanding of email attachments,
2255 where displaying a message is seen to be a single, integrated operation.
2256 Today, email messages are expected to consist of a main text part
2257 plus possibly attachments.
2258 They are not any more seen to be arbitrary MIME hierarchies with
2259 information on how to display the individual parts.
2260 I adjusted
2261 .Pn mhshow 's
2262 behavior to the modern view on the topic.
2263 .P
2264 Note that this section completely ignores the original
2265 .Pn show
2266 program, because it was not capable to display MIME messages
2267 and is no longer part of mmh.
2268 Although
2269 .Pn mhshow
2270 was renamed to
2271 .Pn show
2272 in mmh, this section uses the name
2273 .Pn mhshow ,
2274 in order to avoid confusion.
2275 .P
2276 In mmh, the basic idea is that
2277 .Pn mhshow
2278 should display a message in one single pager session.
2279 Therefore,
2280 .Pn mhshow
2281 invokes a pager session for all its output,
2282 whenever it prints to a terminal.
2283 .Ci a4197ea6ffc5c1550e8b52d5a654bcaaaee04a4e
2284 In consequence,
2285 .Pn mhl
2286 does no more invoke a pager.
2287 .Ci 0e46503be3c855bddaeae3843e1b659279c35d70
2288 With
2289 .Pn mhshow
2290 replacing the original
2291 .Pn show ,
2292 output from
2293 .Pn mhl
2294 does not go to the terminal directly, but through
2295 .Pn mhshow .
2296 Hence,
2297 .Pn mhl
2298 does not need to invoke a pager.
2299 The one and only job of
2300 .Pn mhl
2301 is to format messages or parts of them.
2302 The only place in mmh, where a pager is invoked is
2303 .Pn mhshow .
2304 .P
2305 .Pe mhshow-show-*
2306 profile entries can be used to display MIME parts in a specific way.
2307 For instance, PDF and Postscript files could be converted to plain text
2308 to display them in the terminal.
2309 In mmh, the displaying of MIME parts will always be done serially.
2310 The request to display the MIME type `multipart/parallel' in parallel
2311 is ignored.
2312 It is simply treated as `multipart/mixed'.
2313 .Ci d0581ba306a7299113a346f9b4c46ce97bc4cef6
2314 This could already be requested with the, now removed,
2315 .Sw -serialonly
2316 switch of
2317 .Pn mhshow .
2318 As MIME parts are always processed exclusively , i.e. serially,
2319 the `%e' escape in
2320 .Pe mhshow-show-*
2321 profile entries became useless and was thus removed.
2322 .Ci a20d405db09b7ccca74d3e8c57550883da49e1ae
2323 .P
2324 In the intended setup, only text content would be displayed.
2325 Non-text content would be converted to text by appropriate
2326 .Pe mhshow-show-*
2327 profile entries before, if possible and wanted.
2328 All output would be displayed in a single pager session.
2329 Other kinds of attachments are ignored.
2330 With
2331 .Pe mhshow-show-*
2332 profile entries for them, they can be displayed serially along
2333 the message.
2334 For parallel display, the attachments need to be stored to disk first.
2335 .P
2336 To display text content in foreign charsets, they need to be converted
2337 to the native charset.
2338 Therefore,
2339 .Pe mhshow-charset-*
2340 profile entries used to be needed.
2341 In mmh, the conversion is done automatically by piping the text through
2342 the
2343 .Pn iconv
2344 command, if necessary.
2345 .Ci 2433122c20baccb10b70b49c04c6b0497b5b3b60
2346 Custom
2347 .Pe mhshow-show-*
2348 rules for textual content might need a
2349 .Cl "iconv -f %c %f |
2350 prefix to have the text converted to the native charset.
2351 .P
2352 Although the conversion of foreign charsets to the native one
2353 has improved, it is not consistent enough.
2354 Further work needs to be done and
2355 the basic concepts in this field need to be re-thought.
2356 Though, the default setup of mmh displays message in foreign charsets
2357 correctly without the need to configure anything.
2360 .ig
2362 .P
2363 mhshow/mhstore: Removed support for retrieving message/external-body parts.
2364 These tools won't download the contents automatically anymore. Instead,
2365 they print the information needed to get the contents. If someone should
2366 really receive one of those rare message/external-body messages, he can
2367 do the job manually. We save nearly a thousand lines of code. That's worth
2368 it!
2369 (The profile entry `nmh-access-ftp' and sbr/ruserpass.c for reading
2370 ~/.netrc are gone now.)
2371 .Ci 55e1d8c654ee0f7c45b9361ce34617983b454c32
2373 ..
2377 .H2 "Digital Cryptography
2378 .P
2379 Signing and encryption.
2380 .P
2381 FIXME
2385 .H2 "Modern Defaults
2386 .P
2387 Nmh has a bunch of convenience-improving features inactive by default,
2388 although one can expect every new user wanting to have them active.
2389 The reason they are inactive by default is the wish to stay compatible
2390 with old versions.
2391 But what is the definition for old versions.
2392 Still, the highly useful draft folder facility is not active by default
2393 although it had been introduced over twenty-five years ago
2394 .[
2395 rose romine real work
2396 .]
2397 \(en the community seems not to care.
2398 This is one of several examples that require new users to build up
2399 their profile before they can access the modern features of nmh.
2400 Without an extensively built-up profile, the setup is hardly usable
2401 for modern emailing.
2402 The point is not the customization of the setup,
2403 but the activating of generally useful facilities.
2404 .P
2405 Yet, the real problem lies less in enabling the features, as this is
2406 straight forward as soon as one knows what he wants.
2407 The real problem is that new users need deep insights into the project
2408 before they find out what they are missing and that nmh actually
2409 provides it already, it just was not activated.
2410 To give an example, I needed one year of using nmh
2411 before I became aware of the existence of the attachment system.
2412 One could argue that this fact disqualifies my reading of the
2413 documentation.
2414 If I would have installed nmh from source back then, I could agree.
2415 Yet, I had used a prepackaged version and had expected that it would
2416 just work.
2417 Nevertheless, I had been convinced by the concepts of MH already
2418 and I am a software developer,
2419 still I required a lot of time to discover the cool features.
2420 How can we expect users to be even more advanced than me,
2421 just to allow them use MH in a convenient and modern way?
2422 Unless they are strongly convinced of the concepts, they will fail.
2423 I have seen friends of me giving up disappointed
2424 before they truly used the system,
2425 although they had been motivated in the beginning.
2426 They suffer hard enough to get used to the toolchest approach,
2427 we should spare them further inconveniences.
2428 .P
2429 Maintaining compatibility for its own sake is for no good.
2430 If any MH implementation would be the back-end of widespread
2431 email clients with large user bases, compatibility would be more
2432 important.
2433 Yet, it appears as if this is not the case.
2434 Hence, compatibility is hardly important for technical reasons.
2435 Its importance originates rather from personal reasons.
2436 Nmh's user base is small and old.
2437 Changing the interfaces would cause inconvenience to long-term users of MH.
2438 It would force them to change their many years old MH configurations.
2439 I do understand this aspect, but it keeps new users from using MH.
2440 By sticking to the old users, new users are kept away.
2441 Yet, the future lies in new users.
2442 Hence, mmh invites new users by providing a convenient and modern setup,
2443 readily usable out-of-the-box.
2444 .P
2445 In mmh, all modern features are active by default.
2446 In consequence, a setup with a profile that defines only the path to the
2447 mail storage, is already convenient to use.
2448 Again, Paul Vixie's ``edginess'' appeal supports the direction I took:
2449 ``the `main branch' should just be modern''.
2450 .[
2451 paul vixie edginess nmh-workers
2452 .]
2453 .P
2454 Modern features that are active in mmh by default include:
2455 .BU
2456 The attachment system (\c
2457 .Hd Attach ).
2458 .Ci 8ff284ff9167eff8f5349481529332d59ed913b1
2459 .BU
2460 The draft folder facility (\c
2461 .Fn +drafts ).
2462 .Ci 337338b404931f06f0db2119c9e145e8ca5a9860
2463 .BU
2464 The unseen sequence (`u')
2465 .Ci c2360569e1d8d3678e294eb7c1354cb8bf7501c1
2466 and the sequence negation prefix (`!').
2467 .Ci db74c2bd004b2dc9bf8086a6d8bf773ac051f3cc
2468 .BU
2469 Quoting the original message in the reply.
2470 .Ci 67411b1f95d6ec987b4c732459e1ba8a8ac192c6
2471 .BU
2472 Forwarding messages using MIME.
2473 .Ci 6e271608b7b9c23771523f88d23a4d3593010cf1
2478 .H1 "Code Style
2479 .P
2480 Kernighan and Pike have emphasized the importance of style in the
2481 preface of their book:
2482 .[ [
2483 kernighan pike practice of programming
2484 .], p. x]
2485 .QS
2486 Chapter 1 discusses programming style.
2487 Good style is so important to good programming that we have chose
2488 to cover it first.
2489 .QE
2490 This section covers changes in mmh that were motivated by the desire
2491 to improve on style.
2492 Many of them follow the rules given in the quoted book.
2493 .[
2494 kernighan pike practice of programming
2495 .]
2498 .H2 "Style
2499 .P
2500 .U3 "Indentation Style
2501 .P
2502 Indentation styles are the holy cow of programmers.
2503 Again Kernighan and Pike:
2504 .[ [
2505 kernighan pike practice of programming
2506 .], p. 10]
2507 .QS
2508 Programmers have always argued about the layout of programs,
2509 but the specific style is much less important than its consistent
2510 application.
2511 Pick one style, preferably ours, use it consistently, and don't waste
2512 time arguing.
2513 .QE
2514 .P
2515 I agree that the constant application is most important,
2516 but I believe that some styles have advantages over others.
2517 For instance the indentation with tab characters only.
2518 Tab characters directly map to the nesting level \(en
2519 one tab, one level.
2520 Tab characters are flexible because developers can adjust them to
2521 whatever width they like to have.
2522 There is no more need to run
2523 .Pn unexpand
2524 or
2525 .Pn entab
2526 programs to ensure the correct mixture of leading tabs and spaces.
2527 The simple rules are: (1) Leading whitespace must consist of tabs only.
2528 (2) Any other whitespace should consist of spaces.
2529 These two rules ensure the integrity of the visual appearance.
2530 Although reformatting existing code should be avoided, I did it.
2531 I did not waste time arguing; I just did it.
2532 .Ci a485ed478abbd599d8c9aab48934e7a26733ecb1
2534 .U3 "Comments
2535 .P
2536 Section 1.6 of
2537 .[ [
2538 kernighan pike practice of programming
2539 .], p. 23]
2540 demands: ``Don't belabor the obvious.''
2541 Hence, I simply removed all the comments in the following code excerpt:
2542 .VS
2543 context_replace(curfolder, folder); /* update current folder */
2544 seq_setcur(mp, mp->lowsel); /* update current message */
2545 seq_save(mp); /* synchronize message sequences */
2546 folder_free(mp); /* free folder/message structure */
2547 context_save(); /* save the context file */
2549 [...]
2551 int c; /* current character */
2552 char *cp; /* miscellaneous character pointer */
2554 [...]
2556 /* NUL-terminate the field */
2557 *cp = '\0';
2558 VE
2559 .Ci 426543622b377fc5d091455cba685e114b6df674
2560 .P
2561 The names of the functions explain enough already.
2563 .U3 "Names
2564 .P
2565 Kernighan and Pike suggest:
2566 ``Use active names for functions''.
2567 .[ [
2568 kernighan pike practice of programming
2569 .], p. 4]
2570 One application of this rule was the rename of
2571 .Fu check_charset()
2572 to
2573 .Fu is_native_charset() .
2574 .Ci 8d77b48284c58c135a6b2787e721597346ab056d
2575 The same change fixed a violation of ``Be accurate'' as well.
2576 The code did not match the expectation the function suggested,
2577 as it, for whatever reason, only compared the first ten characters
2578 of the charset name.
2579 .P
2580 More important than using active names is using descriptive names.
2581 Renaming the obscure function
2582 .Fu m_unknown()
2583 was a delightful event.
2584 .Ci 611d68d19204d7cbf5bd585391249cb5bafca846
2585 .P
2586 Magic numbers are generally considered bad style.
2587 Obviously, Kernighan and Pike agree:
2588 ``Give names to magic numbers''.
2589 .[ [
2590 kernighan pike practice of programming
2591 .], p. 19]
2592 One such change was naming the type of input \(en mbox or mail folder \(en
2593 to be scanned:
2594 .VS
2595 #define SCN_MBOX (-1)
2596 #define SCN_FOLD 0
2597 VE
2598 .Ci 7ffb36d28e517a6f3a10272056fc127592ab1c19
2599 .P
2600 The argument
2601 .Ar outnum
2602 of the function
2603 .Fu scan()
2604 in
2605 .Fn uip/scansbr.c
2606 defines the number of the message to be created.
2607 If no message is to be created, the argument is misused to transport
2608 program logic.
2609 This lead to obscure code.
2610 I improved the clarity of the code by introducing two variables:
2611 .VS
2612 int incing = (outnum > 0);
2613 int ismbox = (outnum != 0);
2614 VE
2615 They cover the magic values and are used for conditions.
2616 The variable
2617 .Ar outnum
2618 is only used when it holds an ordinary message number.
2619 .Ci b8b075c77be7794f3ae9ff0e8cedb12b48fd139f
2620 The clarity improvement of the change showed detours in the program logic
2621 of related code parts.
2622 Having the new variables with descriptive names, a more
2623 straight forward implementation became apparent.
2624 Before the clarification was done,
2625 the possibility to improve had not be seen.
2626 .Ci aa60b0ab5e804f8befa890c0a6df0e3143ce0723
2628 .U3 "Rework of \f(CWanno\fP
2629 .P
2630 At the end of their chapter on style,
2631 Kernighan and Pike ask: ``But why worry about style?''
2632 The following example of my rework of
2633 .Pn anno
2634 provides an answer why style is important in the first place.
2635 .P
2636 Until 2002,
2637 .Pn anno
2638 had six functional command line switches,
2639 .Sw -component
2640 and
2641 .Sw -text ,
2642 which took an argument each,
2643 and the two pairs of flags,
2644 .Sw -[no]date
2645 and
2646 .Sw -[no]inplace.,
2647 .Sw -component
2648 and
2649 .Sw -text ,
2650 which took an argument each,
2651 and the two pairs of flags,
2652 .Sw -[no]date
2653 and
2654 .Sw -[no]inplace .
2655 Then Jon Steinhart introduced his attachment system.
2656 In need for more advanced annotation handling, he extended
2657 .Pn anno .
2658 He added five more switches:
2659 .Sw -draft ,
2660 .Sw -list ,
2661 .Sw -delete ,
2662 .Sw -append ,
2663 and
2664 .Sw -number ,
2665 the last one taking an argument.
2666 .Ci 7480dbc14bc90f2d872d434205c0784704213252
2667 Later,
2668 .Sw -[no]preserve
2669 was added.
2670 .Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f
2671 Then, the Synopsis section of the man page
2672 .Mp anno (1)
2673 read:
2674 .VS
2675 anno [+folder] [msgs] [-component field] [-inplace | -noinplace]
2676 [-date | -nodate] [-draft] [-append] [-list] [-delete]
2677 [-number [num|all]] [-preserve | -nopreserve] [-version]
2678 [-help] [-text body]
2679 VE
2680 .LP
2681 The implementation followed the same structure.
2682 Problems became visible when
2683 .Cl "anno -list -number 42
2684 worked on the current message instead on message number 42,
2685 and
2686 .Cl "anno -list -number l:5
2687 did not work on the last five messages but failed with the misterious
2688 error message: ``anno: missing argument to -list''.
2689 Yet, the invocation matched the specification in the man page.
2690 There, the correct use of
2691 .Sw -number
2692 was defined as being
2693 .Cl "[-number [num|all]]
2694 and the textual description for the combination with
2695 .Sw -list
2696 read:
2697 .QS
2698 The -list option produces a listing of the field bodies for
2699 header fields with names matching the specified component,
2700 one per line. The listing is numbered, starting at 1, if
2701 the -number option is also used.
2702 .QE
2703 .LP
2704 The problem was manifold.
2705 The code required a numeric argument to the
2706 .Sw -number
2707 switch.
2708 If it was missing or non-numeric,
2709 .Pn anno
2710 aborted with an error message that had an off-by-one error,
2711 printing the switch one before the failing one.
2712 Semantically, the argument to the
2713 .Sw -number
2714 switch is only necessary in combination with
2715 .Sw -delete ,
2716 but not with
2717 .Sw -list .
2718 In the former case it is even necessary.
2719 .P
2720 Trying to fix these problems on the surface would not have solved it truly.
2721 The problems discovered originate from a discrepance between the semantic
2722 structure of the problem and the structure implemented in the program.
2723 Such structural differences can not be cured on the surface.
2724 They need to be solved by adjusting the structure of the implementation
2725 to the structure of the problem.
2726 .P
2727 In 2002, the new switches
2728 .Sw -list
2729 and
2730 .Sw -delete
2731 were added in the same way, the
2732 .Sw -number
2733 switch for instance had been added.
2734 Yet, they are of structural different type.
2735 Semantically,
2736 .Sw -list
2737 and
2738 .Sw -delete
2739 introduce modes of operation.
2740 Historically,
2741 .Pn anno
2742 had only one operation mode: adding header fields.
2743 With the extension, it got two moder modes:
2744 listing and deleting header fields.
2745 The structure of the code changes did not pay respect to this
2746 fundamental change to
2747 .Pn anno 's
2748 behavior.
2749 Neither the implementation nor the documentation did clearly
2750 define them as being exclusive modes of operation.
2751 Having identified the problem, I solved it by putting structure into
2752 .Pn anno
2753 and its documentation.
2754 .Ci d54c8db8bdf01e8381890f7729bc0ef4a055ea11
2755 .P
2756 The difference is visible in both, the code and the documentation.
2757 The following code excerpt:
2758 .VS
2759 int delete = -2; /* delete header element if set */
2760 int list = 0; /* list header elements if set */
2761 [...]
2762 case DELETESW: /* delete annotations */
2763 delete = 0;
2764 continue;
2765 case LISTSW: /* produce a listing */
2766 list = 1;
2767 continue;
2768 VE
2769 .LP
2770 was replaced by:
2771 .VS
2772 static enum { MODE_ADD, MODE_DEL, MODE_LIST } mode = MODE_ADD;
2773 [...]
2774 case DELETESW: /* delete annotations */
2775 mode = MODE_DEL;
2776 continue;
2777 case LISTSW: /* produce a listing */
2778 mode = MODE_LIST;
2779 continue;
2780 VE
2781 .LP
2782 The replacement code does not only reflect the problem's structure better,
2783 it is easier to understand as well.
2784 The same applies to the documentation.
2785 The man page was completely reorganized to propagate the same structure.
2786 This is visible in the Synopsis section:
2787 .VS
2788 anno [+folder] [msgs] [-component field] [-text body]
2789 [-append] [-date | -nodate] [-preserve | -nopreserve]
2790 [-Version] [-help]
2792 anno -delete [+folder] [msgs] [-component field] [-text
2793 body] [-number num | all ] [-preserve | -nopreserve]
2794 [-Version] [-help]
2796 anno -list [+folder] [msgs] [-component field] [-number]
2797 [-Version] [-help]
2798 VE
2799 .\" XXX think about explaining the -preserve rework?
2803 .H2 "Standard Libraries
2804 .P
2805 MH is one decade older than the POSIX and ANSI C standards.
2806 Hence, MH included own implementations of functions
2807 that are standardized and thus widely available today,
2808 but were not back then.
2809 Today, twenty years after the POSIX and ANSI C were published,
2810 developers can expect system to comply with these standards.
2811 In consequence, MH-specific replacements for standard functions
2812 can and should be dropped.
2813 Kernighan and Pike advise: ``Use standard libraries.''
2814 .[ [
2815 kernighan pike practice of programming
2816 .], p. 196]
2817 Actually, MH had followed this advice in history,
2818 but it had not adjusted to the changes in this field.
2819 The
2820 .Fu snprintf()
2821 function, for instance, was standardized with C99 and is available
2822 almost everywhere because of its high usefulness.
2823 In project's own implementation of
2824 .Fu snprintf()
2825 was dropped in March 2012 in favor for using the one of the
2826 standard library.
2827 .Ci 0052f1024deb0a0a2fc2e5bacf93d45a5a9c9b32
2828 Such decisions limit the portability of mmh
2829 if systems don't support these standardized and widespread functions.
2830 This compromise is made because mmh focuses on the future.
2831 .P
2832 I am not yet thirty years old and my C and Unix experience comprises
2833 only half a dozen years.
2834 Hence, I need to learn about the history in retrospective.
2835 I have not used those ancient constructs myself.
2836 I have not suffered from their incompatibilities.
2837 I have not longed for standardization.
2838 All my programming experience is from a time when ANSI C and POSIX
2839 were well established already.
2840 I have only read a lot of books about the (good) old times.
2841 This puts me in a difficult positions when working with old code.
2842 I need to freshly acquire knowledge about old code constructs and ancient
2843 programming styles, whereas older programmers know these things by
2844 heart from their own experience.
2845 .P
2846 Being aware of the situation, I rather let people with more historic
2847 experience replace ancient code constructs with standardized ones.
2848 Lyndon Nerenberg covered large parts of this task for the nmh project.
2849 He converted project-specific functions to POSIX replacements,
2850 also removing the conditionals compilation of now standardized features.
2851 Ken Hornstein and David Levine had their part in the work, too.
2852 Often, I only needed to pull over changes from nmh into mmh.
2853 These changes include many commits; these are among them:
2854 .Ci 768b5edd9623b7238e12ec8dfc409b82a1ed9e2d
2855 .Ci 0052f1024deb0a0a2fc2e5bacf93d45a5a9c9b32 .
2856 .P
2857 During my own work, I tidied up the \fIMH standard library\fP,
2858 .Fn libmh.a ,
2859 which is located in the
2860 .Fn sbr
2861 (``subroutines'') directory in the source tree.
2862 The MH library includes functions that mmh tools usually need.
2863 Among them are MH-specific functions for profile, context, sequence,
2864 and folder handling, but as well
2865 MH-independent functions, such as auxiliary string functions,
2866 portability interfaces and error-checking wrappers for critical
2867 functions of the standard library.
2868 .P
2869 I have replaced the
2870 .Fu atooi()
2871 function with calls to
2872 .Fu strtoul()
2873 with the third parameter \(en the base \(en set to eight.
2874 .Fu strtoul()
2875 is part of C89 and thus considered safe to use.
2876 .Ci c490c51b3c0f8871b6953bd0c74551404f840a74
2877 .P
2878 I did remove project-included fallback implementations of
2879 .Fu memmove()
2880 and
2881 .Fu strerror() ,
2882 although Peter Maydell had re-included them into nmh in 2008
2883 to support SunOS 4.
2884 Nevertheless, these functions are part of ANSI C.
2885 Systems that do not even provide full ANSI C support should not
2886 put a load on mmh.
2887 .Ci b067ff5c465a5d243ce5a19e562085a9a1a97215
2888 .P
2889 The
2890 .Fu copy()
2891 function copies the string in argument one to the location in two.
2892 In contrast to
2893 .Fu strcpy() ,
2894 it returns a pointer to the terminating null-byte in the destination area.
2895 The code was adjusted to replace
2896 .Fu copy()
2897 with
2898 .Fu strcpy() ,
2899 except within
2900 .Fu concat() ,
2901 where
2902 .Fu copy()
2903 was more convenient.
2904 Therefore, the definition of
2905 .Fu copy()
2906 was moved into the source file of
2907 .Fu concat()
2908 and its visibility is now limited to it.
2909 .Ci 552fd7253e5ee9e554c5c7a8248a6322aa4363bb
2910 .P
2911 The function
2912 .Fu r1bindex()
2913 had been a generalized version of
2914 .Fu basename()
2915 with minor differences.
2916 As all calls to
2917 .Fu r1bindex()
2918 had the slash (`/') as delimiter anyway,
2919 replacing
2920 .Fu r1bindex()
2921 with the more specific and better-named function
2922 .Fu basename()
2923 became desirable.
2924 Unfortunately, many of the 54 calls to
2925 .Fu r1bindex()
2926 depended on a special behavior,
2927 which differed from the POSIX specification for
2928 .Fu basename() .
2929 Hence,
2930 .Fu r1bindex()
2931 was kept but renamed to
2932 .Fu mhbasename() ,
2933 fixing the delimiter to the slash.
2934 .Ci 240013872c392fe644bd4f79382d9f5314b4ea60
2935 For possible uses of
2936 .Fu r1bindex()
2937 with a different delimiter,
2938 the ANSI C function
2939 .Fu strrchr()
2940 provides the core functionality.
2941 .P
2942 The
2943 .Fu ssequal()
2944 function \(en apparently for ``substring equal'' \(en
2945 was renamed to
2946 .Fu isprefix() ,
2947 because this is what it actually checks.
2948 .Ci c20b4fa14515c7ab388ce35411d89a7a92300711
2949 Its source file had included the following comments, no joke.
2950 .VS
2951 /*
2952 * THIS CODE DOES NOT WORK AS ADVERTISED.
2953 * It is actually checking if s1 is a PREFIX of s2.
2954 * All calls to this function need to be checked to see
2955 * if that needs to be changed. Prefix checking is cheaper, so
2956 * should be kept if it's sufficient.
2957 */
2959 /*
2960 * Check if s1 is a substring of s2.
2961 * If yes, then return 1, else return 0.
2962 */
2963 VE
2964 Two months later, it was completely removed by replacing it with
2965 .Fu strncmp() .
2966 .Ci b0b1dd37ff515578cf7cba51625189eb34a196cb
2972 .H2 "Modularization
2973 .P
2974 The source code of the mmh tools is located in the
2975 .Fn uip
2976 (``user interface programs'') directory.
2977 Each tools has a source file with the same name.
2978 For example,
2979 .Pn rmm
2980 is built from
2981 .Fn uip/rmm.c .
2982 Some source files are used for multiple programs.
2983 For example
2984 .Fn uip/scansbr.c
2985 is used for both,
2986 .Pn scan
2987 and
2988 .Pn inc .
2989 In nmh, 49 tools were built from 76 source files.
2990 This is a ratio of 1.6 source files per program.
2991 32 programs depended on multiple source files;
2992 17 programs depended on one source file only.
2993 In mmh, 39 tools are built from 51 source files.
2994 This is a ratio of 1.3 source files per program.
2995 18 programs depend on multiple source files;
2996 21 programs depend on one source file only.
2997 (These numbers and the ones in the following text ignore the MH library
2998 as well as shell scripts and multiple names for the same program.)
2999 .P
3000 Splitting the source code of a large program into multiple files can
3001 increase the readability of its source code.
3002 Most of the mmh tools, however, are simple and staight-forward programs.
3003 With the exception of the MIME handling tools,
3004 .Pn pick
3005 is the largest tools.
3006 It contains 1\|037 lines of source code (measured with
3007 .Pn sloccount ), excluding the MH library.
3008 Only the MIME handling tools (\c
3009 .Pn mhbuild ,
3010 .Pn mhstore ,
3011 .Pn show ,
3012 etc.)
3013 are larger.
3014 Splitting programs with less than 1\|000 lines of code into multiple
3015 source files seldom leads to better readability.
3016 For such tools, splitting makes sense
3017 when parts of the code are reused in other programs,
3018 and the reused code fragment is not general enough
3019 for including it in the MH library,
3020 or, if the code has depencencies on a library that only few programs need.
3021 .Fn uip/packsbr.c ,
3022 for instance, provides the core program logic for the
3023 .Pn packf
3024 and
3025 .Pn rcvpack
3026 programs.
3027 .Fn uip/packf.c
3028 and
3029 .Fn uip/rcvpack.c
3030 mainly wrap the core function appropriately.
3031 No other tools use the folder packing functions.
3032 As another example,
3033 .Fn uip/termsbr.c
3034 provides termcap support, which requires linking with a termcap or
3035 curses library.
3036 Including
3037 .Fn uip/termsbr.c
3038 into the MH library would require every program to be linked with
3039 termcap or curses, although only few of the programs require it.
3040 .P
3041 The task of MIME handling is complex enough that splitting its code
3042 into multiple source files improves the readability.
3043 The program
3044 .Pn mhstore ,
3045 for instance, is compiled out of seven source files with 2\|500
3046 lines of code in summary.
3047 The main code file
3048 .Fn uip/mhstore.c
3049 consists of 800 lines; the other 1\|700 lines of code are reused in
3050 other MIME handling tools.
3051 It seems to be worthwhile to bundle the generic MIME handling code into
3052 a MH-MIME library, as a companion to the MH standard library.
3053 This is left open for the future.
3054 .P
3055 The work already done, focussed on the non-MIME tools.
3056 The amount of code compiled into each program was reduced.
3057 This eases the understanding of the code base.
3058 In nmh,
3059 .Pn comp
3060 was built from six source files:
3061 .Fn comp.c ,
3062 .Fn whatnowproc.c ,
3063 .Fn whatnowsbr.c ,
3064 .Fn sendsbr.c ,
3065 .Fn annosbr.c ,
3066 and
3067 .Fn distsbr.c .
3068 In mmh, it builds from only two:
3069 .Fn comp.c
3070 and
3071 .Fn whatnowproc.c .
3072 In nmh's
3073 .Pn comp ,
3074 the core function of
3075 .Pn whatnow ,
3076 .Pn send ,
3077 and
3078 .Pn anno
3079 were compiled into
3080 .Pn comp .
3081 This saved the need to execute these programs with
3082 .Fu fork()
3083 and
3084 .Fu exec() ,
3085 two expensive system calls.
3086 Whereis this approach improved the time performance,
3087 it interweaved the source code.
3088 Core functionalities were not encapsulated into programs but into
3089 function, which were then wrapped by programs.
3090 For example,
3091 .Fn uip/annosbr.c
3092 included the function
3093 .Fu annotate() .
3094 Each program that wanted to annotate messages, included the source file
3095 .Fn uip/annosbr.c
3096 and called
3097 .Fu annotate() .
3098 Because the function
3099 .Fu annotate()
3100 was used like the tool
3101 .Pn anno ,
3102 it had seven parameters, reflecting the command line switches of the tool.
3103 When another pair of command line switches was added to
3104 .Pn anno ,
3105 a rather ugly hack was implemented to avoid adding another parameter
3106 to the function.
3107 .Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f
3108 .P
3109 Separation simplifies the understanding of program code
3110 because the area influenced by any particular statement is smaller.
3111 The separating on the program-level is more strict than the separation
3112 on the function level.
3113 In mmh, the relevant code of
3114 .Pn comp
3115 comprises the two files
3116 .Fn uip/comp.c
3117 and
3118 .Fn uip/whatnowproc.c ,
3119 together 210 lines of code.
3120 In nmh,
3121 .Pn comp
3122 comprises six files with 2\|450 lines.
3123 Not all of the code in these six files was actually used by
3124 .Pn comp ,
3125 but the code reader needed to read all of the code first to know which
3126 parts were used.
3127 .P
3128 As I have read a lot in the code base during the last two years,
3129 I learned about the easy and the difficult parts.
3130 Code is easy to understand if:
3131 .BU
3132 The influenced code area is small
3133 .BU
3134 The boundaries are stictly defined
3135 .BU
3136 The code is written straight-forward
3137 .P
3138 .\" XXX move this paragraph somewhere else?
3139 Reading
3140 .Pn rmm 's
3141 source code in
3142 .Fn uip/rmm.c
3143 is my recommendation for a beginner's entry point into the code base of nmh.
3144 The reasons are that the task of
3145 .Pn rmm
3146 is straight forward and it consists of one small source code file only,
3147 yet its source includes code constructs typical for MH tools.
3148 With the introduction of the trash folder in mmh,
3149 .Pn rmm
3150 became a bit more complex, because it invokes
3151 .Pn refile .
3152 Still, it is a good example for a simple tool with clear sources.
3153 .P
3154 Understanding
3155 .Pn comp
3156 requires to read 210 lines of code in mmh, but ten times as much in nmh.
3157 Due to the aforementioned hack in
3158 .Pn anno
3159 to save the additional parameter, information passed through the program's
3160 source base in obscure ways.
3161 Thus, understanding
3162 .Pn comp ,
3163 required understanding the inner workings of
3164 .Fn uip/annosbr.c
3165 first.
3166 To be sure to fully understand a program, its whole source code needs
3167 to be examined.
3168 Not doing so is a leap of faith, assuming that the developers
3169 have avoided obscure programming techniques.
3170 By separating the tools on the program-level, the boundaries are
3171 clearly visible and technically enforced.
3172 The interfaces are calls to
3173 .Fu exec()
3174 rather than arbitrary function calls.
3175 .P
3176 But the real problem is another:
3177 Nmh violates the golden ``one tool, one job'' rule of the Unix philosophy.
3178 Understanding
3179 .Pn comp
3180 requires understanding
3181 .Fn uip/annosbr.c
3182 and
3183 .Fn uip/sendsbr.c
3184 because
3185 .Pn comp
3186 does annotate and send messages.
3187 In nmh, there surely exists the tool
3188 .Pn send ,
3189 which does (almost) only send messages.
3190 But
3191 .Pn comp
3192 and
3193 .Pn repl
3194 and
3195 .Pn forw
3196 and
3197 .Pn dist
3198 and
3199 .Pn whatnow
3200 and
3201 .Pn viamail ,
3202 they all (!) have the same message sending function included, too.
3203 In result,
3204 .Pn comp
3205 sends messages without using
3206 .Pn send .
3207 The situation is the same as if
3208 .Pn grep
3209 would page without
3210 .Pn more
3211 just because both programs are part of the same code base.
3212 .P
3213 The clear separation on the surface \(en the toolchest approach \(en
3214 is violated on the level below.
3215 This violation is for the sake of time performance.
3216 On systems where
3217 .Fu fork()
3218 and
3219 .Fu exec()
3220 are expensive, the quicker response might be noticable.
3221 In the old times, sacrifying readability and conceptional beauty for speed
3222 might even have been a must to prevent MH from being unusably slow.
3223 Whatever the reasons had been, today they are gone.
3224 No longer should we sacrifice readability or conceptional beauty.
3225 No longer should we violate the Unix philosophy's ``one tool, one job''
3226 guideline.
3227 No longer should we keep speed improvements that became unnecessary.
3228 .P
3229 Therefore, mmh's
3230 .Pn comp
3231 does no longer send messages.
3232 In mmh, different jobs are divided among separate programs that
3233 invoke each other as needed.
3234 In consequence,
3235 .Pn comp
3236 invokes
3237 .Pn whatnow
3238 which thereafter invokes
3239 .Pn send .
3240 The clear separation on the surface is maintained on the level below.
3241 Human users and the tools use the same interface \(en
3242 annotations, for example, are made by invoking
3243 .Pn anno ,
3244 no matter if requested by programs or by human beings.
3245 The decrease of tools built from multiple source files and thus
3246 the decrease of
3247 .Fn uip/*sbr.c
3248 files confirm the improvement.
3249 .P
3250 One disadvantage needs to be taken with this change:
3251 The compiler can no longer check the integrity of the interfaces.
3252 By changing the command line interfaces of tools, it is
3253 the developer's job to adjust the invocations of these tools as well.
3254 As this is a manual task and regression tests, which could detect such
3255 problems, are not availabe yet, it is prone to errors.
3256 These errors will not be detected at compile time but at run time.
3257 Installing regression tests is a task left to do.
3258 In the best case, a uniform way of invoking tools from other tools
3259 can be developed to allow automated testing at compile time.
3264 .H2 "Separation
3266 .U3 "MH Directory Split
3267 .P
3268 In MH and nmh, a personal setup had consisted of two parts:
3269 The MH profile, named
3270 .Fn \&.mh_profile
3271 and being located directly in the user's home directory.
3272 And the MH directory, where all his mail messages and also his personal
3273 forms, scan formats, other configuration files are stored.
3274 The location
3275 of this directory could be user-chosen.
3276 The default was to name it
3277 .Fn Mail
3278 and have it directly in the home directory.
3279 .P
3280 I've never liked the data storage and the configuration to be intermixed.
3281 They are different kinds of data.
3282 One part, are the messages,
3283 which are the data to operate on.
3284 The other part, are the personal
3285 configuration files, which are able to change the behavior of the operations.
3286 The actual operations are defined in the profile, however.
3287 .P
3288 When storing data, one should try to group data by its type.
3289 There's sense in the Unix file system hierarchy, where configuration
3290 file are stored separate (\c
3291 .Fn /etc )
3292 to the programs (\c
3293 .Fn /bin
3294 and
3295 .Fn /usr/bin )
3296 to their sources (\c
3297 .Fn /usr/src ).
3298 Such separation eases the backup management, for instance.
3299 .P
3300 In mmh, I've reorganized the file locations.
3301 Still there are two places:
3302 There's the mail storage directory, which, like in MH, contains all the
3303 messages, but, unlike in MH, nothing else.
3304 Its location still is user-chosen, with the default name
3305 .Fn Mail ,
3306 in the user's home directory.
3307 This is much similar to the case in nmh.
3308 The configuration files, however, are grouped together in the new directory
3309 .Fn \&.mmh
3310 in the user's home directory.
3311 The user's profile now is a file, named
3312 .Fn profile ,
3313 in this mmh directory.
3314 Consistently, the context file and all the personal forms, scan formats,
3315 and the like, are also there.
3316 .P
3317 The naming changed with the relocation.
3318 The directory where everything, except the profile, had been stored (\c
3319 .Fn $HOME/Mail ),
3320 used to be called \fIMH directory\fP.
3321 Now, this directory is called the
3322 user's \fImail storage\fP.
3323 The name \fImmh directory\fP is now given to
3324 the new directory
3325 (\c
3326 .Fn $HOME/.mmh ),
3327 containing all the personal configuration files.
3328 .P
3329 The separation of the files by type of content is logical and convenient.
3330 There are no functional differences as any possible setup known to me
3331 can be implemented with both approaches, although likely a bit easier
3332 with the new approach.
3333 The main goal of the change had been to provide
3334 sensible storage locations for any type of personal mmh file.
3335 .P
3336 In order for one user to have multiple MH setups, he can use the
3337 environment variable
3338 .Ev MH
3339 the point to a different profile file.
3340 The MH directory (mail storage plus personal configuration files) is
3341 defined by the
3342 .Pe Path
3343 profile entry.
3344 The context file could be defined by the
3345 .Pe context
3346 profile entry or by the
3347 .Ev MHCONTEXT
3348 environment variable.
3349 The latter is useful to have a distinct context (e.g. current folders)
3350 in each terminal window, for instance.
3351 In mmh, there are three environment variables now.
3352 .Ev MMH
3353 may be used to change the location of the mmh directory.
3354 .Ev MMHP
3355 and
3356 .Ev MMHC
3357 change the profile and context files, respectively.
3358 Besides providing a more consistent feel (which simply is the result
3359 of being designed anew), the set of personal configuration files can
3360 be chosen independently from the profile (including mail storage location)
3361 and context, now.
3362 Being it relevant for practical use or not, it
3363 de-facto is an improvement.
3364 However, the main achievement is the
3365 split between mail storage and personal configuration files.
3373 .H1 "Concept Exploitation/Homogeneity
3376 .H2 "Draft Folder
3377 .P
3378 Historically, MH provided exactly one draft message, named
3379 .Fn draft
3380 and
3381 being located in the MH directory.
3382 When starting to compose another message
3383 before the former one was sent, the user had been questioned whether to use,
3384 refile or replace the old draft.
3385 Working on multiple drafts at the same time
3386 was impossible.
3387 One could only work on them in alteration by refiling the
3388 previous one to some directory and fetching some other one for reediting.
3389 This manual draft management needed to be done each time the user wanted
3390 to switch between editing one draft to editing another.
3391 .P
3392 To allow true parallel editing of drafts, in a straight forward way, the
3393 draft folder facility exists.
3394 It had been introduced already in July 1984
3395 by Marshall T. Rose.
3396 The facility was inactive by default.
3397 Even in nmh, the draft folder facility remained inactive by default.
3398 At least, Richard Coleman added the man page
3399 .Mp mh-draft(5)
3400 to document
3401 the feature well.
3402 .P
3403 The only advantage of not using the draft folder facility is the static
3404 name of the draft file.
3405 This could be an issue for MH front-ends like mh-e.
3406 But as they likely want to provide working on multiple drafts in parallel,
3407 the issue is only concerning compatibility.
3408 The aim of nmh to stay compatible
3409 prevented the default activation of the draft folder facility.
3410 .P
3411 On the other hand, a draft folder is the much more natural concept than
3412 a draft message.
3413 MH's mail storage consists of folders and messages,
3414 the messages named with ascending numbers.
3415 A draft message breaks with this
3416 concept by introducing a message in a file named
3417 .Fn draft .
3418 This draft
3419 message is special.
3420 It can not be simply listed with the available tools,
3421 but instead requires special switches.
3422 I.e. corner-cases were
3423 introduced.
3424 A draft folder, in contrast, does not introduce such
3425 corner-cases.
3426 The available tools can operate on the messages within that
3427 folder like on any messages within any mail folders.
3428 The only difference
3429 is the fact that the default folder for
3430 .Pn send
3431 is the draft folder,
3432 instead of the current folder, like for all other tools.
3433 .P
3434 The trivial part of the change was activating the draft folder facility
3435 by default and setting a default name for this folder.
3436 Obviously, I chose
3437 the name
3438 .Fn +drafts .
3439 This made the
3440 .Sw -draftfolder
3441 and
3442 .Sw -draftmessage
3443 switches useless, and I could remove them.
3444 The more difficult but also the part that showed the real improvement,
3445 was updating the tools to the new concept.
3446 .Sw -draft
3447 switches could
3448 be dropped, as operating on a draft message became indistinguishable to
3449 operating on any other message for the tools.
3450 .Pn comp
3451 still has its
3452 .Sw -use
3453 switch for switching between its two modes: (1) Compose a new
3454 draft, possibly by taking some existing message as a form.
3455 (2) Modify
3456 an existing draft.
3457 In either case, the behavior of
3458 .Pn comp is
3459 deterministic.
3460 There is no more need to query the user.
3461 I consider this
3462 a major improvement.
3463 By making
3464 .Pn send
3465 simply operate on the current
3466 message in the draft folder by default, with message and folder both
3467 overridable by specifying them on the command line, it is now possible
3468 to send a draft anywhere within the storage by simply specifying its folder
3469 and name.
3470 .P
3471 All theses changes converted special cases to regular cases, thus
3472 simplifying the tools and increasing the flexibility.
3475 .H2 "Trash Folder
3476 .P
3477 Similar to the situation for drafts is the situation for removed messages.
3478 Historically, a message was deleted by renaming.
3479 A specific
3480 \fIbackup prefix\fP, often comma (\c
3481 .Fn , )
3482 or hash (\c
3483 .Fn # ),
3484 being prepended to the file name.
3485 Thus, MH wouldn't recognize the file
3486 as a message anymore, as only files whose name consists of digits only
3487 are treated as messages.
3488 The removed messages remained as files in the
3489 same directory and needed some maintenance job to truly delete them after
3490 some grace time.
3491 Usually, by running a command similar to
3492 .VS
3493 find /home/user/Mail -ctime +7 -name ',*' | xargs rm
3494 VE
3495 in a cron job.
3496 Within the grace time interval
3497 the original message could be restored by stripping the
3498 the backup prefix from the file name.
3499 If however, the last message of
3500 a folder is been removed \(en say message
3501 .Fn 6
3502 becomes file
3503 .Fn ,6
3504 \(en and a new message enters the same folder, thus the same
3505 numbered being given again \(en in our case
3506 .Fn 6
3507 \(en, if that one
3508 is removed too, then the backup of the former message gets overwritten.
3509 Thus, the ability to restore removed messages does not only depend on
3510 the ``sweeping cron job'' but also on the removing of further messages.
3511 This is undesirable, because the real mechanism is hidden from the user
3512 and the consequences of further removals are not always obvious.
3513 Further more, the backup files are scattered within the whole mail
3514 storage, instead of being collected at one place.
3515 .P
3516 To improve the situation, the profile entry
3517 .Pe rmmproc
3518 (previously named
3519 .Pe Delete-Prog )
3520 was introduced, very early.
3521 It could be set to any command, which would care for the mail removal
3522 instead of taking the default action, described above.
3523 Refiling the to-be-removed files to some garbage folder was a common
3524 example.
3525 Nmh's man page
3526 .Mp rmm(1)
3527 proposes
3528 .Cl "refile +d
3529 to move messages to the garbage folder and
3530 .Cl "rm `mhpath +d all`
3531 the empty the garbage folder.
3532 Managing the message removal this way is a sane approach.
3533 It keeps
3534 the removed messages in one place, makes it easy to remove the backup
3535 files, and, most important, enables the user to use the tools of MH
3536 itself to operate on the removed messages.
3537 One can
3538 .Pn scan
3539 them,
3540 .Pn show
3541 them, and restore them with
3542 .Pn refile .
3543 There's no more
3544 need to use
3545 .Pn mhpath
3546 to switch over from MH tools to Unix tools \(en MH can do it all itself.
3547 .P
3548 This approach matches perfect with the concepts of MH, thus making
3549 it powerful.
3550 Hence, I made it the default.
3551 And even more, I also
3552 removed the old backup prefix approach, as it is clearly less powerful.
3553 Keeping unused alternative in the code is a bad choice as they likely
3554 gather bugs, by not being constantly tested.
3555 Also, the increased code
3556 size and more conditions crease the maintenance costs.
3557 By strictly
3558 converting to the trash folder approach, I simplified the code base.
3559 .Pn rmm
3560 calls
3561 .Pn refile
3562 internally to move the to-be-removed
3563 message to the trash folder (\c
3564 .Fn +trash
3565 by default).
3566 Messages
3567 there can be operated on like on any other message in the storage.
3568 The sweep clean, one can use
3569 .Cl "rmm -unlink +trash a" ,
3570 where the
3571 .Sw -unlink
3572 switch causes the files to be truly unliked instead
3573 of moved to the trash folder.
3576 .H2 "Path Notations
3577 .P
3578 foo
3581 .H2 "MIME Integration
3582 .P
3583 user-visible access to whole messages and MIME parts are inherently
3584 different
3587 .H2 "Of One Cast
3588 .P