docs/master

view discussion.roff @ 122:c234656329e0

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