docs/master

view discussion.roff @ 127:4a9a97d9d6b5

Exchanged the section titles `Style' and `Code Style'.
author markus schnalke <meillo@marmaro.de>
date Sat, 30 Jun 2012 17:22:12 +0200
parents 3aafbd32d77b
children 01af3c0dfe7b
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 "Streamlining
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 streamline 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 streamlined
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 streamlines 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 "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 .]
2500 .H2 "Code Style
2501 .P
2502 .U3 "Indentation Style
2503 .P
2504 Indentation styles are the holy cow of programmers.
2505 Again Kernighan and Pike:
2506 .[ [
2507 kernighan pike practice of programming
2508 .], p. 10]
2509 .QS
2510 Programmers have always argued about the layout of programs,
2511 but the specific style is much less important than its consistent
2512 application.
2513 Pick one style, preferably ours, use it consistently, and don't waste
2514 time arguing.
2515 .QE
2516 .P
2517 I agree that the constant application is most important,
2518 but I believe that some styles have advantages over others.
2519 For instance the indentation with tab characters only.
2520 Tab characters directly map to the nesting level \(en
2521 one tab, one level.
2522 Tab characters are flexible because developers can adjust them to
2523 whatever width they like to have.
2524 There is no more need to run
2525 .Pn unexpand
2526 or
2527 .Pn entab
2528 programs to ensure the correct mixture of leading tabs and spaces.
2529 The simple rules are: (1) Leading whitespace must consist of tabs only.
2530 (2) Any other whitespace should consist of spaces.
2531 These two rules ensure the integrity of the visual appearance.
2532 Although reformatting existing code should be avoided, I did it.
2533 I did not waste time arguing; I just did it.
2534 .Ci a485ed478abbd599d8c9aab48934e7a26733ecb1
2536 .U3 "Comments
2537 .P
2538 Section 1.6 of
2539 .[ [
2540 kernighan pike practice of programming
2541 .], p. 23]
2542 demands: ``Don't belabor the obvious.''
2543 Hence, I simply removed all the comments in the following code excerpt:
2544 .VS
2545 context_replace(curfolder, folder); /* update current folder */
2546 seq_setcur(mp, mp->lowsel); /* update current message */
2547 seq_save(mp); /* synchronize message sequences */
2548 folder_free(mp); /* free folder/message structure */
2549 context_save(); /* save the context file */
2551 [...]
2553 int c; /* current character */
2554 char *cp; /* miscellaneous character pointer */
2556 [...]
2558 /* NUL-terminate the field */
2559 *cp = '\0';
2560 VE
2561 .Ci 426543622b377fc5d091455cba685e114b6df674
2562 .P
2563 The names of the functions explain enough already.
2565 .U3 "Names
2566 .P
2567 Kernighan and Pike suggest:
2568 ``Use active names for functions''.
2569 .[ [
2570 kernighan pike practice of programming
2571 .], p. 4]
2572 One application of this rule was the rename of
2573 .Fu check_charset()
2574 to
2575 .Fu is_native_charset() .
2576 .Ci 8d77b48284c58c135a6b2787e721597346ab056d
2577 The same change fixed a violation of ``Be accurate'' as well.
2578 The code did not match the expectation the function suggested,
2579 as it, for whatever reason, only compared the first ten characters
2580 of the charset name.
2581 .P
2582 More important than using active names is using descriptive names.
2583 Renaming the obscure function
2584 .Fu m_unknown()
2585 was a delightful event.
2586 .Ci 611d68d19204d7cbf5bd585391249cb5bafca846
2587 .P
2588 Magic numbers are generally considered bad style.
2589 Obviously, Kernighan and Pike agree:
2590 ``Give names to magic numbers''.
2591 .[ [
2592 kernighan pike practice of programming
2593 .], p. 19]
2594 One such change was naming the type of input \(en mbox or mail folder \(en
2595 to be scanned:
2596 .VS
2597 #define SCN_MBOX (-1)
2598 #define SCN_FOLD 0
2599 VE
2600 .Ci 7ffb36d28e517a6f3a10272056fc127592ab1c19
2601 .P
2602 The argument
2603 .Ar outnum
2604 of the function
2605 .Fu scan()
2606 in
2607 .Fn uip/scansbr.c
2608 defines the number of the message to be created.
2609 If no message is to be created, the argument is misused to transport
2610 program logic.
2611 This lead to obscure code.
2612 I improved the clarity of the code by introducing two variables:
2613 .VS
2614 int incing = (outnum > 0);
2615 int ismbox = (outnum != 0);
2616 VE
2617 They cover the magic values and are used for conditions.
2618 The variable
2619 .Ar outnum
2620 is only used when it holds an ordinary message number.
2621 .Ci b8b075c77be7794f3ae9ff0e8cedb12b48fd139f
2622 The clarity improvement of the change showed detours in the program logic
2623 of related code parts.
2624 Having the new variables with descriptive names, a more
2625 straight forward implementation became apparent.
2626 Before the clarification was done,
2627 the possibility to improve had not be seen.
2628 .Ci aa60b0ab5e804f8befa890c0a6df0e3143ce0723
2630 .U3 "Rework of \f(CWanno\fP
2631 .P
2632 At the end of their chapter on style,
2633 Kernighan and Pike ask: ``But why worry about style?''
2634 The following example of my rework of
2635 .Pn anno
2636 provides an answer why style is important in the first place.
2637 .P
2638 Until 2002,
2639 .Pn anno
2640 had six functional command line switches,
2641 .Sw -component
2642 and
2643 .Sw -text ,
2644 which took an argument each,
2645 and the two pairs of flags,
2646 .Sw -[no]date
2647 and
2648 .Sw -[no]inplace.,
2649 .Sw -component
2650 and
2651 .Sw -text ,
2652 which took an argument each,
2653 and the two pairs of flags,
2654 .Sw -[no]date
2655 and
2656 .Sw -[no]inplace .
2657 Then Jon Steinhart introduced his attachment system.
2658 In need for more advanced annotation handling, he extended
2659 .Pn anno .
2660 He added five more switches:
2661 .Sw -draft ,
2662 .Sw -list ,
2663 .Sw -delete ,
2664 .Sw -append ,
2665 and
2666 .Sw -number ,
2667 the last one taking an argument.
2668 .Ci 7480dbc14bc90f2d872d434205c0784704213252
2669 Later,
2670 .Sw -[no]preserve
2671 was added.
2672 .Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f
2673 Then, the Synopsis section of the man page
2674 .Mp anno (1)
2675 read:
2676 .VS
2677 anno [+folder] [msgs] [-component field] [-inplace | -noinplace]
2678 [-date | -nodate] [-draft] [-append] [-list] [-delete]
2679 [-number [num|all]] [-preserve | -nopreserve] [-version]
2680 [-help] [-text body]
2681 VE
2682 .LP
2683 The implementation followed the same structure.
2684 Problems became visible when
2685 .Cl "anno -list -number 42
2686 worked on the current message instead on message number 42,
2687 and
2688 .Cl "anno -list -number l:5
2689 did not work on the last five messages but failed with the mysterious
2690 error message: ``anno: missing argument to -list''.
2691 Yet, the invocation matched the specification in the man page.
2692 There, the correct use of
2693 .Sw -number
2694 was defined as being
2695 .Cl "[-number [num|all]]
2696 and the textual description for the combination with
2697 .Sw -list
2698 read:
2699 .QS
2700 The -list option produces a listing of the field bodies for
2701 header fields with names matching the specified component,
2702 one per line. The listing is numbered, starting at 1, if
2703 the -number option is also used.
2704 .QE
2705 .LP
2706 The problem was manifold.
2707 The code required a numeric argument to the
2708 .Sw -number
2709 switch.
2710 If it was missing or non-numeric,
2711 .Pn anno
2712 aborted with an error message that had an off-by-one error,
2713 printing the switch one before the failing one.
2714 Semantically, the argument to the
2715 .Sw -number
2716 switch is only necessary in combination with
2717 .Sw -delete ,
2718 but not with
2719 .Sw -list .
2720 In the former case it is even necessary.
2721 .P
2722 Trying to fix these problems on the surface would not have solved it truly.
2723 The problems discovered originate from a discrepance between the semantic
2724 structure of the problem and the structure implemented in the program.
2725 Such structural differences can not be cured on the surface.
2726 They need to be solved by adjusting the structure of the implementation
2727 to the structure of the problem.
2728 .P
2729 In 2002, the new switches
2730 .Sw -list
2731 and
2732 .Sw -delete
2733 were added in the same way, the
2734 .Sw -number
2735 switch for instance had been added.
2736 Yet, they are of structural different type.
2737 Semantically,
2738 .Sw -list
2739 and
2740 .Sw -delete
2741 introduce modes of operation.
2742 Historically,
2743 .Pn anno
2744 had only one operation mode: adding header fields.
2745 With the extension, it got two moder modes:
2746 listing and deleting header fields.
2747 The structure of the code changes did not pay respect to this
2748 fundamental change to
2749 .Pn anno 's
2750 behavior.
2751 Neither the implementation nor the documentation did clearly
2752 define them as being exclusive modes of operation.
2753 Having identified the problem, I solved it by putting structure into
2754 .Pn anno
2755 and its documentation.
2756 .Ci d54c8db8bdf01e8381890f7729bc0ef4a055ea11
2757 .P
2758 The difference is visible in both, the code and the documentation.
2759 The following code excerpt:
2760 .VS
2761 int delete = -2; /* delete header element if set */
2762 int list = 0; /* list header elements if set */
2763 [...]
2764 case DELETESW: /* delete annotations */
2765 delete = 0;
2766 continue;
2767 case LISTSW: /* produce a listing */
2768 list = 1;
2769 continue;
2770 VE
2771 .LP
2772 was replaced by:
2773 .VS
2774 static enum { MODE_ADD, MODE_DEL, MODE_LIST } mode = MODE_ADD;
2775 [...]
2776 case DELETESW: /* delete annotations */
2777 mode = MODE_DEL;
2778 continue;
2779 case LISTSW: /* produce a listing */
2780 mode = MODE_LIST;
2781 continue;
2782 VE
2783 .LP
2784 The replacement code does not only reflect the problem's structure better,
2785 it is easier to understand as well.
2786 The same applies to the documentation.
2787 The man page was completely reorganized to propagate the same structure.
2788 This is visible in the Synopsis section:
2789 .VS
2790 anno [+folder] [msgs] [-component field] [-text body]
2791 [-append] [-date | -nodate] [-preserve | -nopreserve]
2792 [-Version] [-help]
2794 anno -delete [+folder] [msgs] [-component field] [-text
2795 body] [-number num | all ] [-preserve | -nopreserve]
2796 [-Version] [-help]
2798 anno -list [+folder] [msgs] [-component field] [-number]
2799 [-Version] [-help]
2800 VE
2801 .\" XXX think about explaining the -preserve rework?
2806 .H2 "Standard Libraries
2807 .P
2808 MH is one decade older than the POSIX and ANSI C standards.
2809 Hence, MH included own implementations of functions
2810 that are standardized and thus widely available today,
2811 but were not back then.
2812 Today, twenty years after the POSIX and ANSI C were published,
2813 developers can expect system to comply with these standards.
2814 In consequence, MH-specific replacements for standard functions
2815 can and should be dropped.
2816 Kernighan and Pike advise: ``Use standard libraries.''
2817 .[ [
2818 kernighan pike practice of programming
2819 .], p. 196]
2820 Actually, MH had followed this advice in history,
2821 but it had not adjusted to the changes in this field.
2822 The
2823 .Fu snprintf()
2824 function, for instance, was standardized with C99 and is available
2825 almost everywhere because of its high usefulness.
2826 In project's own implementation of
2827 .Fu snprintf()
2828 was dropped in March 2012 in favor for using the one of the
2829 standard library.
2830 .Ci 0052f1024deb0a0a2fc2e5bacf93d45a5a9c9b32
2831 Such decisions limit the portability of mmh
2832 if systems don't support these standardized and widespread functions.
2833 This compromise is made because mmh focuses on the future.
2834 .P
2835 I am not yet thirty years old and my C and Unix experience comprises
2836 only half a dozen years.
2837 Hence, I need to learn about the history in retrospective.
2838 I have not used those ancient constructs myself.
2839 I have not suffered from their incompatibilities.
2840 I have not longed for standardization.
2841 All my programming experience is from a time when ANSI C and POSIX
2842 were well established already.
2843 I have only read a lot of books about the (good) old times.
2844 This puts me in a difficult positions when working with old code.
2845 I need to freshly acquire knowledge about old code constructs and ancient
2846 programming styles, whereas older programmers know these things by
2847 heart from their own experience.
2848 .P
2849 Being aware of the situation, I rather let people with more historic
2850 experience replace ancient code constructs with standardized ones.
2851 Lyndon Nerenberg covered large parts of this task for the nmh project.
2852 He converted project-specific functions to POSIX replacements,
2853 also removing the conditionals compilation of now standardized features.
2854 Ken Hornstein and David Levine had their part in the work, too.
2855 Often, I only needed to pull over changes from nmh into mmh.
2856 These changes include many commits; these are among them:
2857 .Ci 768b5edd9623b7238e12ec8dfc409b82a1ed9e2d
2858 .Ci 0052f1024deb0a0a2fc2e5bacf93d45a5a9c9b32 .
2859 .P
2860 During my own work, I tidied up the \fIMH standard library\fP,
2861 .Fn libmh.a ,
2862 which is located in the
2863 .Fn sbr
2864 (``subroutines'') directory in the source tree.
2865 The MH library includes functions that mmh tools usually need.
2866 Among them are MH-specific functions for profile, context, sequence,
2867 and folder handling, but as well
2868 MH-independent functions, such as auxiliary string functions,
2869 portability interfaces and error-checking wrappers for critical
2870 functions of the standard library.
2871 .P
2872 I have replaced the
2873 .Fu atooi()
2874 function with calls to
2875 .Fu strtoul()
2876 with the third parameter \(en the base \(en set to eight.
2877 .Fu strtoul()
2878 is part of C89 and thus considered safe to use.
2879 .Ci c490c51b3c0f8871b6953bd0c74551404f840a74
2880 .P
2881 I did remove project-included fallback implementations of
2882 .Fu memmove()
2883 and
2884 .Fu strerror() ,
2885 although Peter Maydell had re-included them into nmh in 2008
2886 to support SunOS 4.
2887 Nevertheless, these functions are part of ANSI C.
2888 Systems that do not even provide full ANSI C support should not
2889 put a load on mmh.
2890 .Ci b067ff5c465a5d243ce5a19e562085a9a1a97215
2891 .P
2892 The
2893 .Fu copy()
2894 function copies the string in argument one to the location in two.
2895 In contrast to
2896 .Fu strcpy() ,
2897 it returns a pointer to the terminating null-byte in the destination area.
2898 The code was adjusted to replace
2899 .Fu copy()
2900 with
2901 .Fu strcpy() ,
2902 except within
2903 .Fu concat() ,
2904 where
2905 .Fu copy()
2906 was more convenient.
2907 Therefore, the definition of
2908 .Fu copy()
2909 was moved into the source file of
2910 .Fu concat()
2911 and its visibility is now limited to it.
2912 .Ci 552fd7253e5ee9e554c5c7a8248a6322aa4363bb
2913 .P
2914 The function
2915 .Fu r1bindex()
2916 had been a generalized version of
2917 .Fu basename()
2918 with minor differences.
2919 As all calls to
2920 .Fu r1bindex()
2921 had the slash (`/') as delimiter anyway,
2922 replacing
2923 .Fu r1bindex()
2924 with the more specific and better-named function
2925 .Fu basename()
2926 became desirable.
2927 Unfortunately, many of the 54 calls to
2928 .Fu r1bindex()
2929 depended on a special behavior,
2930 which differed from the POSIX specification for
2931 .Fu basename() .
2932 Hence,
2933 .Fu r1bindex()
2934 was kept but renamed to
2935 .Fu mhbasename() ,
2936 fixing the delimiter to the slash.
2937 .Ci 240013872c392fe644bd4f79382d9f5314b4ea60
2938 For possible uses of
2939 .Fu r1bindex()
2940 with a different delimiter,
2941 the ANSI C function
2942 .Fu strrchr()
2943 provides the core functionality.
2944 .P
2945 The
2946 .Fu ssequal()
2947 function \(en apparently for ``substring equal'' \(en
2948 was renamed to
2949 .Fu isprefix() ,
2950 because this is what it actually checks.
2951 .Ci c20b4fa14515c7ab388ce35411d89a7a92300711
2952 Its source file had included the following comments, no joke.
2953 .VS
2954 /*
2955 * THIS CODE DOES NOT WORK AS ADVERTISED.
2956 * It is actually checking if s1 is a PREFIX of s2.
2957 * All calls to this function need to be checked to see
2958 * if that needs to be changed. Prefix checking is cheaper, so
2959 * should be kept if it's sufficient.
2960 */
2962 /*
2963 * Check if s1 is a substring of s2.
2964 * If yes, then return 1, else return 0.
2965 */
2966 VE
2967 Two months later, it was completely removed by replacing it with
2968 .Fu strncmp() .
2969 .Ci b0b1dd37ff515578cf7cba51625189eb34a196cb
2974 .H2 "Modularization
2975 .P
2976 The source code of the mmh tools is located in the
2977 .Fn uip
2978 (``user interface programs'') directory.
2979 Each tools has a source file with the same name.
2980 For example,
2981 .Pn rmm
2982 is built from
2983 .Fn uip/rmm.c .
2984 Some source files are used for multiple programs.
2985 For example
2986 .Fn uip/scansbr.c
2987 is used for both,
2988 .Pn scan
2989 and
2990 .Pn inc .
2991 In nmh, 49 tools were built from 76 source files.
2992 This is a ratio of 1.6 source files per program.
2993 32 programs depended on multiple source files;
2994 17 programs depended on one source file only.
2995 In mmh, 39 tools are built from 51 source files.
2996 This is a ratio of 1.3 source files per program.
2997 18 programs depend on multiple source files;
2998 21 programs depend on one source file only.
2999 (These numbers and the ones in the following text ignore the MH library
3000 as well as shell scripts and multiple names for the same program.)
3001 .P
3002 Splitting the source code of a large program into multiple files can
3003 increase the readability of its source code.
3004 Most of the mmh tools, however, are simple and straight-forward programs.
3005 With the exception of the MIME handling tools,
3006 .Pn pick
3007 is the largest tools.
3008 It contains 1\|037 lines of source code (measured with
3009 .Pn sloccount ), excluding the MH library.
3010 Only the MIME handling tools (\c
3011 .Pn mhbuild ,
3012 .Pn mhstore ,
3013 .Pn show ,
3014 etc.)
3015 are larger.
3016 Splitting programs with less than 1\|000 lines of code into multiple
3017 source files seldom leads to better readability.
3018 For such tools, splitting makes sense
3019 when parts of the code are reused in other programs,
3020 and the reused code fragment is not general enough
3021 for including it in the MH library,
3022 or, if the code has dependencies on a library that only few programs need.
3023 .Fn uip/packsbr.c ,
3024 for instance, provides the core program logic for the
3025 .Pn packf
3026 and
3027 .Pn rcvpack
3028 programs.
3029 .Fn uip/packf.c
3030 and
3031 .Fn uip/rcvpack.c
3032 mainly wrap the core function appropriately.
3033 No other tools use the folder packing functions.
3034 As another example,
3035 .Fn uip/termsbr.c
3036 provides termcap support, which requires linking with a termcap or
3037 curses library.
3038 Including
3039 .Fn uip/termsbr.c
3040 into the MH library would require every program to be linked with
3041 termcap or curses, although only few of the programs require it.
3042 .P
3043 The task of MIME handling is complex enough that splitting its code
3044 into multiple source files improves the readability.
3045 The program
3046 .Pn mhstore ,
3047 for instance, is compiled out of seven source files with 2\|500
3048 lines of code in summary.
3049 The main code file
3050 .Fn uip/mhstore.c
3051 consists of 800 lines; the other 1\|700 lines of code are reused in
3052 other MIME handling tools.
3053 It seems to be worthwhile to bundle the generic MIME handling code into
3054 a MH-MIME library, as a companion to the MH standard library.
3055 This is left open for the future.
3056 .P
3057 The work already done, focussed on the non-MIME tools.
3058 The amount of code compiled into each program was reduced.
3059 This eases the understanding of the code base.
3060 In nmh,
3061 .Pn comp
3062 was built from six source files:
3063 .Fn comp.c ,
3064 .Fn whatnowproc.c ,
3065 .Fn whatnowsbr.c ,
3066 .Fn sendsbr.c ,
3067 .Fn annosbr.c ,
3068 and
3069 .Fn distsbr.c .
3070 In mmh, it builds from only two:
3071 .Fn comp.c
3072 and
3073 .Fn whatnowproc.c .
3074 In nmh's
3075 .Pn comp ,
3076 the core function of
3077 .Pn whatnow ,
3078 .Pn send ,
3079 and
3080 .Pn anno
3081 were compiled into
3082 .Pn comp .
3083 This saved the need to execute these programs with
3084 .Fu fork()
3085 and
3086 .Fu exec() ,
3087 two expensive system calls.
3088 Whereis this approach improved the time performance,
3089 it interweaved the source code.
3090 Core functionalities were not encapsulated into programs but into
3091 function, which were then wrapped by programs.
3092 For example,
3093 .Fn uip/annosbr.c
3094 included the function
3095 .Fu annotate() .
3096 Each program that wanted to annotate messages, included the source file
3097 .Fn uip/annosbr.c
3098 and called
3099 .Fu annotate() .
3100 Because the function
3101 .Fu annotate()
3102 was used like the tool
3103 .Pn anno ,
3104 it had seven parameters, reflecting the command line switches of the tool.
3105 When another pair of command line switches was added to
3106 .Pn anno ,
3107 a rather ugly hack was implemented to avoid adding another parameter
3108 to the function.
3109 .Ci d9b1d57351d104d7ec1a5621f090657dcce8cb7f
3110 .P
3111 Separation simplifies the understanding of program code
3112 because the area influenced by any particular statement is smaller.
3113 The separating on the program-level is more strict than the separation
3114 on the function level.
3115 In mmh, the relevant code of
3116 .Pn comp
3117 comprises the two files
3118 .Fn uip/comp.c
3119 and
3120 .Fn uip/whatnowproc.c ,
3121 together 210 lines of code.
3122 In nmh,
3123 .Pn comp
3124 comprises six files with 2\|450 lines.
3125 Not all of the code in these six files was actually used by
3126 .Pn comp ,
3127 but the code reader needed to read all of the code first to know which
3128 parts were used.
3129 .P
3130 As I have read a lot in the code base during the last two years,
3131 I learned about the easy and the difficult parts.
3132 Code is easy to understand if:
3133 .BU
3134 The influenced code area is small
3135 .BU
3136 The boundaries are strictly defined
3137 .BU
3138 The code is written straight-forward
3139 .P
3140 .\" XXX move this paragraph somewhere else?
3141 Reading
3142 .Pn rmm 's
3143 source code in
3144 .Fn uip/rmm.c
3145 is my recommendation for a beginner's entry point into the code base of nmh.
3146 The reasons are that the task of
3147 .Pn rmm
3148 is straight forward and it consists of one small source code file only,
3149 yet its source includes code constructs typical for MH tools.
3150 With the introduction of the trash folder in mmh,
3151 .Pn rmm
3152 became a bit more complex, because it invokes
3153 .Pn refile .
3154 Still, it is a good example for a simple tool with clear sources.
3155 .P
3156 Understanding
3157 .Pn comp
3158 requires to read 210 lines of code in mmh, but ten times as much in nmh.
3159 Due to the aforementioned hack in
3160 .Pn anno
3161 to save the additional parameter, information passed through the program's
3162 source base in obscure ways.
3163 Thus, understanding
3164 .Pn comp ,
3165 required understanding the inner workings of
3166 .Fn uip/annosbr.c
3167 first.
3168 To be sure to fully understand a program, its whole source code needs
3169 to be examined.
3170 Not doing so is a leap of faith, assuming that the developers
3171 have avoided obscure programming techniques.
3172 By separating the tools on the program-level, the boundaries are
3173 clearly visible and technically enforced.
3174 The interfaces are calls to
3175 .Fu exec()
3176 rather than arbitrary function calls.
3177 .P
3178 But the real problem is another:
3179 Nmh violates the golden ``one tool, one job'' rule of the Unix philosophy.
3180 Understanding
3181 .Pn comp
3182 requires understanding
3183 .Fn uip/annosbr.c
3184 and
3185 .Fn uip/sendsbr.c
3186 because
3187 .Pn comp
3188 does annotate and send messages.
3189 In nmh, there surely exists the tool
3190 .Pn send ,
3191 which does (almost) only send messages.
3192 But
3193 .Pn comp
3194 and
3195 .Pn repl
3196 and
3197 .Pn forw
3198 and
3199 .Pn dist
3200 and
3201 .Pn whatnow
3202 and
3203 .Pn viamail ,
3204 they all (!) have the same message sending function included, too.
3205 In result,
3206 .Pn comp
3207 sends messages without using
3208 .Pn send .
3209 The situation is the same as if
3210 .Pn grep
3211 would page without
3212 .Pn more
3213 just because both programs are part of the same code base.
3214 .P
3215 The clear separation on the surface \(en the toolchest approach \(en
3216 is violated on the level below.
3217 This violation is for the sake of time performance.
3218 On systems where
3219 .Fu fork()
3220 and
3221 .Fu exec()
3222 are expensive, the quicker response might be noticable.
3223 In the old times, sacrificing readability and conceptional beauty for
3224 speed might even have been a must to prevent MH from being unusably slow.
3225 Whatever the reasons had been, today they are gone.
3226 No longer should we sacrifice readability or conceptional beauty.
3227 No longer should we violate the Unix philosophy's ``one tool, one job''
3228 guideline.
3229 No longer should we keep speed improvements that became unnecessary.
3230 .P
3231 Therefore, mmh's
3232 .Pn comp
3233 does no longer send messages.
3234 In mmh, different jobs are divided among separate programs that
3235 invoke each other as needed.
3236 In consequence,
3237 .Pn comp
3238 invokes
3239 .Pn whatnow
3240 which thereafter invokes
3241 .Pn send .
3242 The clear separation on the surface is maintained on the level below.
3243 Human users and the tools use the same interface \(en
3244 annotations, for example, are made by invoking
3245 .Pn anno ,
3246 no matter if requested by programs or by human beings.
3247 The decrease of tools built from multiple source files and thus
3248 the decrease of
3249 .Fn uip/*sbr.c
3250 files confirm the improvement.
3251 .P
3252 One disadvantage needs to be taken with this change:
3253 The compiler can no longer check the integrity of the interfaces.
3254 By changing the command line interfaces of tools, it is
3255 the developer's job to adjust the invocations of these tools as well.
3256 As this is a manual task and regression tests, which could detect such
3257 problems, are not available yet, it is prone to errors.
3258 These errors will not be detected at compile time but at run time.
3259 Installing regression tests is a task left to do.
3260 In the best case, a uniform way of invoking tools from other tools
3261 can be developed to allow automated testing at compile time.
3266 .H2 "User Data Locations
3267 .P
3268 In nmh, a personal setup consists of the MH profile and the MH directory.
3269 The profile is a file named
3270 .Fn \&.mh_profile
3271 in the user's home directory.
3272 It contains the static configuration.
3273 It also contains the location of the MH directory in the profile entry
3274 .Pe Path .
3275 The MH directory contains the mail storage and is the first
3276 place to search for personal forms, scan formats, and similar
3277 configuration files.
3278 The location of the MH directory can be chosen freely by the user.
3279 The default and usual name is a directory named
3280 .Fn Mail
3281 in the home directory.
3282 .P
3283 The way MH data is splitted between profile and MH directory is a legacy.
3284 It is only sensible in a situation where the profile is the only
3285 configuration file.
3286 Why else should the mail storage and the configuration files be intermixed?
3287 They are different kinds of data:
3288 The data to be operated on and the configuration to change how
3289 tools operate.
3290 Splitting the configuration between the profile and the MH directory
3291 is bad.
3292 Merging the mail storage and the configuration in one directory is bad
3293 as well.
3294 As the mail storage and the configuration were not separated sensibly
3295 in the first place, I did it now.
3296 .P
3297 Personal mmh data is grouped by type, resulting in two distinct parts:
3298 The mail storage and the configuration.
3299 In mmh, the mail storage directory still contains all the messages,
3300 but, in exception of public sequences files, nothing else.
3301 In difference to nmh, the auxiliary configuration files are no longer
3302 located there.
3303 Therefore, the directory is no longer called the user's \fIMH directory\fP
3304 but his \fImail storage\fP.
3305 Its location is still user-chosen, with the default name
3306 .Fn Mail ,
3307 in the user's home directory.
3308 In mmh, the configuration is grouped together in
3309 the hidden directory
3310 .Fn \&.mmh
3311 in the user's home directory.
3312 This \fImmh directory\fP contains the context file, personal forms,
3313 scan formats, and the like, but also the user's profile, now named
3314 .Fn profile .
3315 The location of the profile is no longer fixed to
3316 .Fn $HOME/.mh_profile
3317 but to
3318 .Fn $HOME/.mmh/profile .
3319 Having both, the file
3320 .Fn $HOME/.mh_profile
3321 and the configuration directory
3322 .Fn $HOME/.mmh
3323 appeared to be inconsistent.
3324 The approach chosen for mmh is consistent, simple, and familiar to
3325 Unix users.
3326 .P
3327 MH allows users to have multiiple MH setups.
3328 Therefore, it is necessary to select a different profile.
3329 The profile is the single entry point to access the rest of a
3330 personal MH setup.
3331 In nmh, the environment variable
3332 .Ev MH
3333 could be used to specifiy a different profile.
3334 To operate in the same MH setup with a separate context,
3335 the
3336 .Ev MHCONTEXT
3337 environment variable could be used.
3338 This allows having own current folders and current messages in
3339 each terminal, for instance.
3340 In mmh, three environment variables are used.
3341 .Ev MMH
3342 overrides the default location of the mmh directory (\c
3343 .Fn .mmh ).
3344 .Ev MMHP
3345 and
3346 .Ev MMHC
3347 override the paths to the profile and context files, respectively.
3348 This approach allows the set of personal configuration files to be chosen
3349 independently from the profile, context, and mail storage.
3350 .P
3351 The separation of the files by type is sensible and convenient.
3352 The new approach has no functional disadvantages,
3353 as every setup I can imagine can be implemented with both approaches,
3354 possibly even easier with the new approach.
3355 The main achievement of the change is the clear and sensible split
3356 between mail storage and configuration.
3363 .H1 "Concept Exploitation/Homogeneity
3366 .H2 "Draft Folder
3367 .P
3368 Historically, MH provided exactly one draft message, named
3369 .Fn draft
3370 and
3371 being located in the MH directory.
3372 When starting to compose another message
3373 before the former one was sent, the user had been questioned whether to use,
3374 refile or replace the old draft.
3375 Working on multiple drafts at the same time
3376 was impossible.
3377 One could only work on them in alteration by refiling the
3378 previous one to some directory and fetching some other one for reediting.
3379 This manual draft management needed to be done each time the user wanted
3380 to switch between editing one draft to editing another.
3381 .P
3382 To allow true parallel editing of drafts, in a straight forward way, the
3383 draft folder facility exists.
3384 It had been introduced already in July 1984
3385 by Marshall T. Rose.
3386 The facility was inactive by default.
3387 Even in nmh, the draft folder facility remained inactive by default.
3388 At least, Richard Coleman added the man page
3389 .Mp mh-draft(5)
3390 to document
3391 the feature well.
3392 .P
3393 The only advantage of not using the draft folder facility is the static
3394 name of the draft file.
3395 This could be an issue for MH front-ends like mh-e.
3396 But as they likely want to provide working on multiple drafts in parallel,
3397 the issue is only concerning compatibility.
3398 The aim of nmh to stay compatible
3399 prevented the default activation of the draft folder facility.
3400 .P
3401 On the other hand, a draft folder is the much more natural concept than
3402 a draft message.
3403 MH's mail storage consists of folders and messages,
3404 the messages named with ascending numbers.
3405 A draft message breaks with this
3406 concept by introducing a message in a file named
3407 .Fn draft .
3408 This draft
3409 message is special.
3410 It can not be simply listed with the available tools,
3411 but instead requires special switches.
3412 I.e. corner-cases were
3413 introduced.
3414 A draft folder, in contrast, does not introduce such
3415 corner-cases.
3416 The available tools can operate on the messages within that
3417 folder like on any messages within any mail folders.
3418 The only difference
3419 is the fact that the default folder for
3420 .Pn send
3421 is the draft folder,
3422 instead of the current folder, like for all other tools.
3423 .P
3424 The trivial part of the change was activating the draft folder facility
3425 by default and setting a default name for this folder.
3426 Obviously, I chose
3427 the name
3428 .Fn +drafts .
3429 This made the
3430 .Sw -draftfolder
3431 and
3432 .Sw -draftmessage
3433 switches useless, and I could remove them.
3434 The more difficult but also the part that showed the real improvement,
3435 was updating the tools to the new concept.
3436 .Sw -draft
3437 switches could
3438 be dropped, as operating on a draft message became indistinguishable to
3439 operating on any other message for the tools.
3440 .Pn comp
3441 still has its
3442 .Sw -use
3443 switch for switching between its two modes: (1) Compose a new
3444 draft, possibly by taking some existing message as a form.
3445 (2) Modify
3446 an existing draft.
3447 In either case, the behavior of
3448 .Pn comp is
3449 deterministic.
3450 There is no more need to query the user.
3451 I consider this
3452 a major improvement.
3453 By making
3454 .Pn send
3455 simply operate on the current
3456 message in the draft folder by default, with message and folder both
3457 overridable by specifying them on the command line, it is now possible
3458 to send a draft anywhere within the storage by simply specifying its folder
3459 and name.
3460 .P
3461 All theses changes converted special cases to regular cases, thus
3462 simplifying the tools and increasing the flexibility.
3465 .H2 "Trash Folder
3466 .P
3467 Similar to the situation for drafts is the situation for removed messages.
3468 Historically, a message was deleted by renaming.
3469 A specific
3470 \fIbackup prefix\fP, often comma (\c
3471 .Fn , )
3472 or hash (\c
3473 .Fn # ),
3474 being prepended to the file name.
3475 Thus, MH wouldn't recognize the file
3476 as a message anymore, as only files whose name consists of digits only
3477 are treated as messages.
3478 The removed messages remained as files in the
3479 same directory and needed some maintenance job to truly delete them after
3480 some grace time.
3481 Usually, by running a command similar to
3482 .VS
3483 find /home/user/Mail -ctime +7 -name ',*' | xargs rm
3484 VE
3485 in a cron job.
3486 Within the grace time interval
3487 the original message could be restored by stripping the
3488 the backup prefix from the file name.
3489 If however, the last message of
3490 a folder is been removed \(en say message
3491 .Fn 6
3492 becomes file
3493 .Fn ,6
3494 \(en and a new message enters the same folder, thus the same
3495 numbered being given again \(en in our case
3496 .Fn 6
3497 \(en, if that one
3498 is removed too, then the backup of the former message gets overwritten.
3499 Thus, the ability to restore removed messages does not only depend on
3500 the ``sweeping cron job'' but also on the removing of further messages.
3501 This is undesirable, because the real mechanism is hidden from the user
3502 and the consequences of further removals are not always obvious.
3503 Further more, the backup files are scattered within the whole mail
3504 storage, instead of being collected at one place.
3505 .P
3506 To improve the situation, the profile entry
3507 .Pe rmmproc
3508 (previously named
3509 .Pe Delete-Prog )
3510 was introduced, very early.
3511 It could be set to any command, which would care for the mail removal
3512 instead of taking the default action, described above.
3513 Refiling the to-be-removed files to some garbage folder was a common
3514 example.
3515 Nmh's man page
3516 .Mp rmm(1)
3517 proposes
3518 .Cl "refile +d
3519 to move messages to the garbage folder and
3520 .Cl "rm `mhpath +d all`
3521 the empty the garbage folder.
3522 Managing the message removal this way is a sane approach.
3523 It keeps
3524 the removed messages in one place, makes it easy to remove the backup
3525 files, and, most important, enables the user to use the tools of MH
3526 itself to operate on the removed messages.
3527 One can
3528 .Pn scan
3529 them,
3530 .Pn show
3531 them, and restore them with
3532 .Pn refile .
3533 There's no more
3534 need to use
3535 .Pn mhpath
3536 to switch over from MH tools to Unix tools \(en MH can do it all itself.
3537 .P
3538 This approach matches perfect with the concepts of MH, thus making
3539 it powerful.
3540 Hence, I made it the default.
3541 And even more, I also
3542 removed the old backup prefix approach, as it is clearly less powerful.
3543 Keeping unused alternative in the code is a bad choice as they likely
3544 gather bugs, by not being constantly tested.
3545 Also, the increased code
3546 size and more conditions crease the maintenance costs.
3547 By strictly
3548 converting to the trash folder approach, I simplified the code base.
3549 .Pn rmm
3550 calls
3551 .Pn refile
3552 internally to move the to-be-removed
3553 message to the trash folder (\c
3554 .Fn +trash
3555 by default).
3556 Messages
3557 there can be operated on like on any other message in the storage.
3558 The sweep clean, one can use
3559 .Cl "rmm -unlink +trash a" ,
3560 where the
3561 .Sw -unlink
3562 switch causes the files to be truly unliked instead
3563 of moved to the trash folder.
3566 .H2 "Path Notations
3567 .P
3568 foo
3571 .H2 "MIME Integration
3572 .P
3573 user-visible access to whole messages and MIME parts are inherently
3574 different
3577 .H2 "Of One Cast
3578 .P