docs/master

view discussion.roff @ 133:02660c14f6a8

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