meillo@0: .H0 "Work Report meillo@0: .P meillo@0: foo meillo@0: .P meillo@0: bar meillo@0: meillo@12: .H1 "Removal of Code Relicts meillo@0: .P meillo@20: The code base of mmh originates from the late 70s, had been extensively meillo@12: worked on in the mid 80s, and had been partly reorganized and extended meillo@12: in the 90s. Relicts of all those times had gathered in the code base. meillo@12: My goal was to remove any ancient code parts. One part of the task was meillo@12: converting obsolete code constructs to standard constructs, the other part meillo@12: was dropping obsolete functions. meillo@12: .P meillo@12: As I'm not even thirty years old and have no more than seven years of meillo@12: Unix experience, I needed to learn about the history in retroperspective. meillo@12: Older people likely have used those ancient constructs themself meillo@12: and have suffered from their incompatiblities and have longed for meillo@12: standardization. Unfortunately, I have only read that others had done so. meillo@12: This put me in a much more difficult positions when working on the old meillo@12: code. I needed to recherche what other would have known by heart from meillo@12: experience. All my programming experience comes from a time past ANSI C meillo@12: and past POSIX. Although I knew about the times before, I took the meillo@12: current state implicitely for granted most of the time. meillo@12: .P meillo@12: Being aware of meillo@12: these facts, I rather let people with more historic experience solve the meillo@12: task of converting the ancient code constructs to standardized ones. meillo@12: Luckily, Lyndon Nerenberg focused on this task at the nmh project. meillo@12: He converted large parts of the code to POSIX constructs, removing meillo@12: the conditionals compilation for now standardized features. meillo@12: I'm thankful for this task being solved. I only pulled the changes into meillo@12: mmh. meillo@12: .P meillo@20: The other task \(en dropping ancient functionality to remove old code \(en meillo@12: I did myself, though. My position to strip mmh to the bare minimum of meillo@12: frequently used features is much more revolutional than the nmh community meillo@20: likes it. Without the need to justify my decisions, I was able to quickly meillo@20: remove functionality I considered ancient. meillo@20: The need to discuss my decisions with meillo@20: peers likely would have slowed this process down. Of course, I researched meillo@12: if a particular feature really should be dropped. Having not had any meillo@12: contact to this feature within my computer life was a first indicator to meillo@12: drop it, but I also asked others and searched the literature for modern meillo@12: usage of the feature. If it appeared to be truly ancient, I dropped it. meillo@12: The reason for dropping is always part of the commit message in the meillo@12: version control system. Thus, it is easy for others to check their meillo@12: view on the topic with mine and possibly to argue for reinclusion. meillo@12: meillo@12: .U2 "MMDF maildrop support meillo@12: .P meillo@12: I did drop any support for the MMDF maildrop format. This type of format meillo@12: is conceptionally similar to the mbox format, but uses four bytes with meillo@12: value 1 (\fL^A^A^A^A\fP) as message delimiter, meillo@18: instead of the string ``\fLFrom\ \fP''. meillo@12: Due to the similarity and mbox being the de-facto standard maildrop meillo@12: format on Unix, but also due to the larger influence of Sendmail than MMDF, meillo@12: the MMDF maildrop format had vanished. meillo@12: .P meillo@12: The simplifications within the code were only moderate. Switches could meillo@12: be removed from tools like meillo@12: .L packf , meillo@12: which generate packed mailboxes. Only one packed mailbox format remained: meillo@12: mbox. meillo@12: The most important changes affect the equally named mail parsing routine in meillo@12: .L sbr/m_getfld.c . meillo@12: The direct MMDF code had been removed, but as now only one packed mailbox meillo@12: format is left, code structure simplifications are likely possible. meillo@12: The reason why they are still outstanding is the heavily optimized code meillo@18: of meillo@18: .Fu m_getfld() . meillo@18: Changes beyond a small local scope \(en meillo@12: which restructuring in its core is \(en cause a high risk of damaging meillo@12: the intricate workings of the optimized code. This problem is know meillo@12: to the developers of nmh, too. They also avoid touching this minefield meillo@12: if possible. meillo@12: meillo@12: .U2 "UUCP Bang Paths meillo@12: .P meillo@12: More questionably than the former topic is the removal of support for the meillo@12: UUCP bang path address style. However, the user may translate the bang meillo@12: paths on retrieval to Internet addresses and the other way on posting meillo@12: messages. The former can be done my an MDA like procmail; the latter meillo@12: by a sendmail wrapper. This would ensure that any address handling would meillo@12: work as expected. However, it might just work well without any meillo@12: such modifications, as mmh does not touch addresses much, in general. meillo@12: But I can't ensure as I have never used an environment with bang paths. meillo@12: Also, the behavior might break at any point in further development. meillo@12: meillo@12: .U2 "Hardcopy terminal support meillo@12: .P meillo@12: More of a funny anecdote is the remaining of a check for printing to a meillo@12: hardcopy terminal until Spring 2012, when I finally removed it. meillo@12: I surely would be very happy to see such a terminal in action, maybe meillo@12: actually being able to work on it, but I fear my chances are null. meillo@12: .P meillo@12: The check only prevented a pager to be placed between the outputting meillo@18: program (\c meillo@18: .Pn mhl ) meillo@18: and the terminal. This could have been ensured with meillo@18: the meillo@18: .Sw \-nomoreproc meillo@18: at the command line statically, too. meillo@12: meillo@12: .U2 "Removed support for header fields meillo@12: .P meillo@12: The `Encrypted' header had been introduced by RFC\^822, but already meillo@12: marked legacy in RFC 2822. It was superseded by FIXME. meillo@12: Mmh does no more support this header. meillo@12: .P meillo@12: `Content-MD5' headers were introduced by RFC\^1864. They provide only meillo@12: a verification of data corruption during the transfer. By no means can meillo@12: they ensure verbatim end-to-end delivery of the contents. This is clearly meillo@12: stated in the RFC. The proper approach to provide verificationability meillo@12: of content in an end-to-end relationship is the use of digital cryptography meillo@12: (RFCs FIXME). On the other hand, transfer protocols should ensure the meillo@12: integrity of the transmission. In combinations these two approaches meillo@12: make the `Content-MD5' header field useless. In consequence, I removed meillo@12: the support for it. By this removal, MD5 computation is not needed meillo@12: anywhere in mmh. Hence, over 500 lines of code were removed by this one meillo@12: change. Even if the `Content-MD5' header field is useful sometimes, meillo@12: I value its usefulnes less than the improvement in maintainability, caused meillo@12: by the removal. meillo@12: meillo@20: .U2 "Prompter's Control Keys meillo@20: .P meillo@20: The program meillo@20: .Pn prompter meillo@20: queries the user to fill in a message form. When used by meillo@20: .Pn comp meillo@20: as: meillo@20: .DS meillo@20: comp \-editor prompter meillo@20: .DE meillo@20: the resulting behavior is similar to meillo@20: .Pn mailx . meillo@20: Appearently, meillo@20: .Pn prompter meillo@20: hadn't been touched lately. Otherwise it's hardly explainable why it meillo@20: still offered the switches meillo@20: .Sn \-erase \fUchr\fP meillo@20: and meillo@20: .Sn \-kill \fUchr\fP meillo@20: to name the characters for command line editing. meillo@20: The times when this had been neccessary are long time gone. meillo@20: Today these things work out-of-the-box, and if not, are configured meillo@20: with the standard tool meillo@20: .Pn stty . meillo@20: meillo@12: meillo@14: .H1 "Draft and Trash Folders meillo@16: .U2 "Draft Folder meillo@14: .P meillo@18: Historically, MH provided exactly one draft message, named meillo@18: .Fn draft meillo@18: and meillo@14: being located in the MH directory. When starting to compose another message meillo@14: before the former one was sent, the user had been questioned wether to use, meillo@14: refile or replace the old draft. Working on multiple drafts at the same time meillo@14: was impossible. One could only work on them in alteration by refiling the meillo@14: previous one to some directory and fetching some other one for reediting. meillo@14: This manual draft management needed to be done each time the user wanted meillo@14: to switch between editing one draft to editing another. meillo@14: .P meillo@14: To allow true parallel editing of drafts, in a straight forward way, the meillo@14: draft folder facility exists. It had been introduced already in July 1984 meillo@14: by Marshall T. Rose. The facility was deactivated by default. meillo@14: Even in nmh, the draft folder facility remained deactivated by default. meillo@18: At least, Richard Coleman added the man page meillo@18: .Mp mh-draft(5) meillo@18: to document meillo@14: the feature well. meillo@14: .P meillo@14: The only advantage of not using the draft folder facility is the static meillo@14: name of the draft file. This could be an issue for MH frontends like mh-e. meillo@14: But as they likely want to provide working on multiple drafts in parallel, meillo@14: the issue is only concerning compatibility. The aim of nmh to stay compatible meillo@14: prevented the default activation of the draft folder facility. meillo@14: .P meillo@14: On the other hand, a draft folder is the much more natural concept than meillo@14: a draft message. MH's mail storage consists of folders and messages, meillo@14: the messages named with ascending numbers. A draft message breaks with this meillo@18: concept by introducing a message in a file named meillo@18: .Fn draft . meillo@18: This draft meillo@14: message is special. It can not be simply listed with the available tools, meillo@17: but instead requires special switches. I.e. corner-cases were meillo@14: introduced. A draft folder, in contrast, does not introduce such meillo@14: corner-cases. The available tools can operate on the messages within that meillo@14: folder like on any messages within any mail folders. The only difference meillo@18: is the fact that the default folder for meillo@18: .Pn send meillo@18: is the draft folder, meillo@14: instead of the current folder, like for all other tools. meillo@14: .P meillo@14: The trivial part of the change was activating the draft folder facility meillo@14: by default and setting a default name for this folder. Obviously, I chose meillo@18: the name meillo@18: .Fn +drafts . meillo@18: This made the meillo@18: .Sw \-draftfolder meillo@18: and meillo@18: .Sw \-draftmessage meillo@18: switches useless, and I could remove them. meillo@14: The more difficult but also the part that showed the real improvement, meillo@18: was updating the tools to the new concept. meillo@18: .Sw \-draft meillo@18: switches could meillo@14: be dropped, as operating on a draft message became indistinguishable to meillo@18: operating on any other message for the tools. meillo@18: .Pn comp meillo@18: still has its meillo@18: .Sw \-use meillo@18: switch for switching between its two modes: (1) Compose a new meillo@14: draft, possibly by taking some existing message as a form. (2) Modify meillo@18: an existing draft. In either case, the behavior of meillo@18: .Pn comp is meillo@14: deterministic. There is no more need to query the user. I consider this meillo@18: a major improvement. By making meillo@18: .Pn send meillo@18: simply operate on the current meillo@17: message in the draft folder by default, with message and folder both meillo@14: overridable by specifying them on the command line, it is now possible meillo@17: to send a draft anywhere within the storage by simply specifying its folder meillo@17: and name. meillo@14: .P meillo@14: All theses changes converted special cases to regular cases, thus meillo@14: simplifying the tools and increasing the flexibility. meillo@14: meillo@16: .U2 "Trash Folder meillo@16: .P meillo@16: Similar to the situation for drafts is the situation for removed messages. meillo@16: Historically, a message was deleted by renaming. A specific meillo@18: \fIbackup prefix\fP, often comma (\c meillo@18: .Fn , ) meillo@18: or hash (\c meillo@18: .Fn # ), meillo@16: being prepended to the file name. Thus, MH wouldn't recognize the file meillo@16: as a message anymore, as only files whose name consists of digits only meillo@16: are treated as messages. The removed messages remained as files in the meillo@16: same directory and needed some maintenance job to truly delete them after meillo@16: some grace time. Usually, by running a command similar to meillo@16: .DS meillo@16: find /home/user/Mail \-ctime +7 \-name ',*' | xargs rm meillo@16: .DE meillo@16: in a cron job. Within the grace time interval meillo@16: the original message could be restored by stripping the meillo@16: the backup prefix from the file name. If however, the last message of meillo@18: a folder is been removed \(en say message meillo@18: .Fn 6 meillo@18: becomes file meillo@18: .Fn ,6 meillo@18: \(en and a new message enters the same folder, thus the same meillo@18: numbered being given again \(en in our case meillo@18: .Fn 6 meillo@18: \(en, if that one meillo@17: is removed too, then the backup of the former message gets overwritten. meillo@16: Thus, the ability to restore removed messages does not only depend on meillo@16: the ``sweeping cron job'' but also on the removing of further messages. meillo@16: This is undesireable, because the real mechanism is hidden from the user meillo@16: and the concequences of further removals are not always obvious. meillo@16: Further more, the backup files are scattered within the whole mail meillo@16: storage, instead of being collected at one place. meillo@16: .P meillo@18: To improve the situation, the profile entry meillo@18: .Pe rmmproc meillo@18: (previously named meillo@18: .Pe Delete-Prog ) meillo@18: was introduced, very early. meillo@16: It could be set to any command, which would care for the mail removal meillo@16: instead of taking the default action, described above. meillo@16: Refiling the to-be-removed files to some wastebin folder was a common meillo@18: example. Nmh's man page meillo@18: .Mp rmm(1) meillo@18: proposes meillo@18: .Cl "refile +d meillo@18: to move messages to the wastebin and meillo@18: .Cl "rm `mhpath +d all` meillo@16: the empty the wastebin. meillo@16: Managing the message removal this way is a sane approach. It keeps meillo@16: the removed messages in one place, makes it easy to remove the backup meillo@16: files, and, most important, enables the user to use the tools of MH meillo@18: itself to operate on the removed messages. One can meillo@18: .Pn scan meillo@18: them, meillo@18: .Pn show meillo@18: them, and restore them with meillo@18: .Pn refile . meillo@18: There's no more meillo@18: need to use meillo@18: .Pn mhpath meillo@18: to switch over from MH tools to Unix tools \(en MH can do it all itself. meillo@16: .P meillo@18: This apporach matches perfect with the concepts of MH, thus making meillo@16: it powerful. Hence, I made it the default. And even more, I also meillo@16: removed the old backup prefix approach, as it is clearly less powerful. meillo@16: Keeping unused alternative in the code is a bad choice as they likely meillo@16: gather bugs, by not being constantly tested. Also, the increased code meillo@16: size and more conditions crease the maintenance costs. By strictly meillo@16: converting to the trash folder approach, I simplified the code base. meillo@18: .Pn rmm meillo@18: calls meillo@18: .Pn refile meillo@18: internally to move the to-be-removed meillo@18: message to the trash folder (\c meillo@18: .Fn +trash meillo@18: by default). Messages meillo@16: there can be operated on like on any other message in the storage. meillo@18: The sweep clean, one can use meillo@18: .Cl "rmm \-unlink +trash a" , meillo@18: where the meillo@18: .Sw \-unlink meillo@18: switch causes the files to be truly unliked instead meillo@16: of moved to the trash folder. meillo@16: meillo@0: meillo@17: .H1 "MH Directory Split meillo@0: .P meillo@19: In MH and nmh, a personal setup had consisted of two parts: meillo@19: The MH profile, named meillo@19: .Fn \&.mh_profile meillo@19: and being located directly in the user's home directory. meillo@19: And the MH directory, where all his mail messages and also his personal meillo@19: forms, scan formats, other configuration files are stored. The location meillo@19: of this directory could be user-chosen. The default was to name it meillo@19: .Fn Mail meillo@19: and have it directly in the home directory. meillo@19: .P meillo@19: I've never liked the data storage and the configuration to be intermixed. meillo@19: They are different kinds of data. One part, are the messages, meillo@19: which are the data to operate on. The other part, are the personal meillo@19: configuration files, which are able to change the behavior of the operations. meillo@19: The actual operations are defined in the profile, however. meillo@19: .P meillo@19: When storing data, one should try to group data by its type. meillo@19: There's sense in the Unix file system hierarchy, where configuration meillo@19: file are stored separate (\c meillo@19: .Fn /etc ) meillo@19: to the programs (\c meillo@19: .Fn /bin meillo@19: and meillo@19: .Fn /usr/bin ) meillo@19: to their sources (\c meillo@19: .Fn /usr/src ). meillo@19: Such separation eases the backup management, for instance. meillo@19: .P meillo@19: In mmh, I've reorganized the file locations. meillo@19: Still there are two places: meillo@19: There's the mail storage directory, which, like in MH, contains all the meillo@19: messages, but, unlike in MH, nothing else. meillo@19: Its location still is user-chosen, with the default name meillo@19: .Fn Mail , meillo@19: in the user's home directory. This is much similar to the case in nmh. meillo@19: The configuration files, however, are grouped together in the new directory meillo@19: .Fn \&.mmh meillo@19: in the user's home directory. meillo@19: The user's profile now is a file, named meillo@19: .Fn profile , meillo@19: in this mmh directory. meillo@19: Consistently, the context file and all the personal forms, scan formats, meillo@19: and the like, are also there. meillo@19: .P meillo@19: The naming changed with the relocation. meillo@19: The directory where everything, except the profile, had been stored (\c meillo@19: .Fn $HOME/Mail ), meillo@19: used to be called \fIMH directory\fP. Now, this directory is called the meillo@19: user's \fImail storage\fP. The name \fImmh directory\fP is now given to meillo@19: the new directory meillo@19: (\c meillo@19: .Fn $HOME/.mmh ), meillo@19: containing all the personal configuration files. meillo@19: .P meillo@19: The separation of the files by type of content is logical and convenient. meillo@19: There are no functional differences as any possible setup known to me meillo@19: can be implemented with both approaches, although likely a bit easier meillo@19: with the new approach. The main goal of the change had been to provide meillo@19: sensible storage locations for any type of personal mmh file. meillo@19: .P meillo@19: In order for one user to have multiple MH setups, he can use the meillo@19: environment variable meillo@19: .Ev MH meillo@19: the point to a different profile file. meillo@19: The MH directory (mail storage plus personal configuration files) is meillo@19: defined by the meillo@19: .Pe Path meillo@19: profile entry. meillo@19: The context file could be defined by the meillo@19: .Pe context meillo@19: profile entry or by the meillo@19: .Ev MHCONTEXT meillo@19: environment variable. meillo@19: The latter is useful to have a distinct context (e.g. current folders) meillo@19: in each terminal window, for instance. meillo@19: In mmh, there are three environment variables now. meillo@19: .Ev MMH meillo@19: may be used to change the location of the mmh directory. meillo@19: .Ev MMHP meillo@19: and meillo@19: .Ev MMHC meillo@19: change the profile and context files, respectively. meillo@19: Besides providing a more consistent feel (which simply is the result meillo@19: of being designed anew), the set of personal configuration files can meillo@19: be chosen independently from the profile (including mail storage location) meillo@19: and context, now. Being it relevant for practical use or not, it meillo@19: de-facto is an improvement. However, the main achievement is the meillo@19: split between mail storage and personal configuration files. meillo@17: meillo@0: meillo@0: .H1 "Path Notations meillo@0: .P meillo@0: foo meillo@0: meillo@0: .H1 "Attachments meillo@0: .P meillo@0: foo meillo@0: meillo@20: .H1 "mhshow to show Transition meillo@20: .P meillo@20: Since the very beginning, already in the first concept paper, meillo@20: .Pn show meillo@20: had been MH's mail display program. meillo@20: .Pn show meillo@20: found out which pathnames the relevant messages had and invoked meillo@20: .Pn mhl meillo@20: then to let it render the content. meillo@20: With the advent of MIME, this approach wasn't sufficient anymore. meillo@20: MIME messages can consist of multiple parts, some of which aren't meillo@20: directly displayable, and text content can be encoded in meillo@20: foreign charsets. meillo@20: .Pn show 's meillo@20: simple approach and meillo@20: .Pn mhl 's meillo@20: limited display facilities couldn't cope with the task any longer. meillo@20: Instead of extending these tools, new ones were written from scratch meillo@20: and then added to the MH toolchest. Doing so is encouraged by the meillo@20: toolchest approach. The new tools could be added without interfearing meillo@20: with the existing ones. This is great. It allowed MH to be the meillo@20: first MUA to implement MIME. meillo@20: .P meillo@20: The new MIME features were added in form of the single program meillo@20: .Pn mhn . meillo@20: The command meillo@20: .DS meillo@20: mhn \-show 42 meillo@20: .DE meillo@20: would show the MIME message numbered 42. meillo@20: With the 1.0 release of nmh in February 1999, Richard Coleman finished meillo@20: the split of meillo@20: .Pn mhn meillo@20: into a set of specialized programs, which together covered the meillo@20: aspects of MIME. One of these resulting tools was meillo@20: .Pn mhshow . meillo@20: meillo@20: meillo@0: .H1 "Blind Carbon Copies meillo@0: .P meillo@0: foo meillo@0: meillo@0: .H1 "Good Defaults meillo@0: .P meillo@0: foo meillo@0: meillo@0: .H1 "Modularization meillo@0: .P meillo@0: foo meillo@0: meillo@0: .H1 "Code style meillo@0: .P meillo@0: foo