nonstatic function for atexit, check if atexit fails
[mmh] / docs / README.attachments
1 Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4 A bunch of changes have been made to improve the nmh user interface for
5 handling MIME attachments.
6
7 Why Did I Do This?
8 ~~~~~~~~~~~~~~~~~~
9
10 Although nmh contains the necessary functionality for MIME message handing,
11 the interface to this functionality is pretty obtuse.  There's no way that
12 I'm ever going to convince my partner to write mhbuild composition files!
13 And even though I know how to write them, I often screw up when sending a
14 message that contains a shell script because I forget that I have to double
15 any # at the start of a line, which shell scripts have galore.
16
17 These changes simplify the task of managing attachments on draft files.
18 They allow attachments to be added, listed, and deleted.  MIME messages are
19 automatically created when drafts with attachments are sent.
20
21 The Simple Setup
22 ~~~~~~~~~~~~~~~~
23
24 The gory details are all given below.  Here's how to set things up simply.  This
25 only works if you're using the "standard" interface, i.e., whatnow.  Life is more
26 complicated if you run mh-e.
27
28 Add the following to your .mh_profile:
29
30         send: -attach X-MH-Attachment
31         whatnow: -attach X-MH-Attachment
32
33 You may already have send and whatnow lines in your .mh_profile; if you do, just add
34 the new stuff to the end of the line.  For example, mine looks like:
35
36         send: -alias aliases -attach X-MH-Attachment
37         whatnow: -attach X-MH-Attachment
38
39 That's it.  Next time you want to send an attachment, say "attach filename" at the
40 whatnow prompt and you're done.  You can check your attachments by saying "alist".
41
42 Did I Do This Correctly?
43 ~~~~~~~~~~~~~~~~~~~~~~~~
44
45 Hard to say.  Despite lots of time looking at the nmh code, I can't say that
46 I get the philosophy behind its structure.
47
48 I am aware of two deviations from what I saw in the nmh code.
49
50  1.  I commented my changes.
51
52  2.  It's been years since I've used a VT-100, so I don't try to make code
53      fit into 80 columns anymore.  Seems silly to me.
54
55 What Did I Do?
56 ~~~~~~~~~~~~~~
57
58 I made changes to the following files:
59
60         h/
61                 prototypes.h
62         man/
63                 anno.man
64                 send.man
65                 whatnow.man
66         uip/
67                 Makefile.in
68                 anno.c
69                 annosbr.c
70                 send.c
71                 sendsbr.c
72                 viamail.c       (needed change for new sendsbr argument)
73                 whatnowsbr.c
74
75 Attachments are associated with messages using header fields.  For example, a
76 draft that looks like this
77
78         To: jon
79         Subject: test of attachments
80         X-MH-Attachment: /export/home/jon/foo
81         X-MH-Attachment: /export/home/jon/bar
82         X-MH-Attachment: /export/home/jon/test/foo
83         --------
84
85 has the files "foo", "bar", and foo as attachments.
86
87 Although I use the header field name "X-MH-Attachment" to indicate
88 attachments, the implementation allows any header field name.
89
90 The advantage of using header fields is that the list of attachments
91 travels with the draft so it remains valid across editing sessions.
92
93 Note that the header fields for attachments are removed from the message
94 before it is sent.
95
96 Since I was adding header fields to messages, it seemed sensible to use the
97 existing anno program to do this for me.  This required several changes to
98 generalize anno:
99
100  o  I added a -draft option that permits annotations (header fields) to
101     be added to the draft instead of a message sequence.
102
103  o  I added a -delete option that allows annotations to be deleted.
104
105  o  I added a -list option that allows annotations to be listed.
106
107  o  I added a -number option that modifies the behavior of -delete and -list.
108
109  o  I added a -append option so that annotations are appended to the headers
110     instead of the default prepend.  Without this, attachments come out in
111     reverse order.
112
113 Using the modified anno, the example above could be created (assuming that the
114 draft exists) by
115
116         prompt% anno -draft -comp X-MH-Attachment -text /export/home/jon/foo -nodate -append
117         prompt% anno -draft -comp X-MH-Attachment -text /export/home/jon/bar -nodate -append
118         prompt% anno -draft -comp X-MH-Attachment -text /export/home/jon/test/foo -nodate -append
119
120 One can quite easily make an "attach" command using shell scripts, aliases or functions.
121 For example, here's a bash function that does the job:
122
123         function attach() { for i in $*; do anno -append -nodate -draft -comp X-MH-Attachment -text "$i"; done; }
124
125 The following examples show the different ways in which attachments can be
126 listed.
127
128         prompt% anno -list -draft -comp X-MH-Attachment
129         foo
130         bar
131         foo
132
133         prompt% anno -list -draft -comp X-MH-Attachment -text /
134         /export/home/jon/foo
135         /export/home/jon/bar
136         /export/home/jon/test/foo
137
138         prompt% anno -list -draft -comp X-MH-Attachment -number
139         1       foo
140         2       bar
141         3       foo
142
143         prompt% anno -list -draft -comp X-MH-Attachment -text / -number
144         1       /export/home/jon/foo
145         2       /export/home/jon/bar
146         3       /export/home/jon/test/foo
147
148         prompt%
149
150 Why all these listing options?
151
152 I feel that the listing as produced by the first example is what most people
153 would want most of the time.
154
155 The listing as produced by the second example seemed necessary for situations
156 where there were several attachments with the same file name in different
157 directories.
158
159 I included the numbering option so that attachments could be deleted by number
160 which might be easier in situations where there were several attachments with
161 the same file name in different directories, as in the above example.
162
163 Attachments are deleted using the -delete option.
164
165         prompt% anno -delete -draft -comp X-MH-Attachment -text foo
166
167 deletes the first attachment since the foo matches the basename of the attachment
168 name.
169
170         prompt% anno -delete -draft -comp X-MH-Attachment -text /export/home/jon/test/foo
171
172 deletes the third attachment since the text is a full path name and matches.
173
174         prompt% anno -delete -draft -comp X-MH-Attachment -number 2
175
176 deletes the second attachment.
177
178 The attachment annotations are converted to a MIME message by send.  I'm not
179 completely sure that this is the right place to do it, as opposed to doing
180 it in post, but both would work.  It seemed to me to make more sense to do
181 it in send so that all of the various post options would apply to the MIME
182 message instead of the original draft file.
183
184 I added an -attach option to send that specifies the header field name used
185 for attachments.  Send performs the following additional steps if this option
186 is set:
187
188  o  It scans the header of the draft for attachments.  Normal behavior applies
189     if none exist.
190
191  o  A temporary mhbuild composition file is created if there are attachments.
192
193  o  All non-attachment headers are copied from the draft file to the
194     composition file.
195
196  o  The body of the draft is copied to a temporary body file if it contains at
197     least one non-whitespace character.  A mhbuild directive for this file is
198     appended to the composition file.  Note that this eliminates the problem
199     of lines beginning with the # character in the message body.
200
201  o  A mhbuild directive is appended to the composition file for each attachment
202     header.
203
204  o  mhbuild is run on the composition file, converting it to a MIME message.
205
206  o  The converted composition file is substituted for the original draft file
207     and run through the rest of send.
208
209  o  The original draft file is renamed instead of the converted composition
210     file.  This preserves the original message instead of the composition file
211     which is really what a user would want.
212
213  o  The ,file.orig file created by mhbuild is removed as it's a nuisance.
214
215 The mhbuild directives appended to the composition file are constructed as
216 follows:
217
218  o  The content-type a file with a dot-suffix is obtained from the list of
219     mhshow-suffix- entries in the profile.
220
221  o  A file with no dot-suffix or no entry in the profile is assigned a
222     content-type of application/octet-stream if it contains any non-ASCII
223     characters.
224
225  o  A file with no dot-suffix or no entry in the profile is assigned a
226     content-type of text/plain if it contains only ASCII characters.
227
228  o  The directive is of the form:
229
230         #content-type; name="basename"; x-unix-mode=mode [ description ] filename
231
232     The content type is derived as discussed above.  The basename is the
233     last component of the pathname given in the body of the attachment header
234     field.  The mode is file permissions.  The description is obtained by
235     running the file command on the attachment file.  The filename is the
236     field body from the attachment header field.
237
238 I added an -attach option to whatnow that specifies the header field name for
239 attachments.
240
241 I added to the commands available at the whatnow prompt to provide an interface
242 to the attachment mechanism.
243
244 I'm not completely happy with some of these additions because they duplicate
245 shell functionality.  I'm not sure that there's a good way around it other than
246 to not use whatnow.
247
248 The first three additions (the ones I'm not happy with) are cd, ls, and pwd.
249 These do the same thing as their system counterparts.  As a matter of fact,
250 these are implemented by running the commands in a subshell.  I did this because
251 I wanted proper interpretation of shell-specific things like ~ and wildcard
252 expansion.
253
254 The next command is attach.  This takes a list of files and adds them to the draft
255 as attachments using the same code as the modified anno.  The list of files is
256 run through ls using the user's shell, so wildcard expansion and all that works.
257
258 The alist command lists the attachments on the current draft using listing function
259 that I added to anno.  It takes two optional options, -l for a long listing meaning
260 full path names, and -n for a numbered listing.
261
262 The detach command removes attachments from the current draft, again using the
263 modified anno.  The arguments are interpreted as numbers if the -n option is used,
264 otherwise they're interpreted as file names.  File names are shoveled through ls
265 using the user's shell in the directory containing the file for wildcard expansion
266 and such.  File names are matched against the last pathname component unless they
267 begin with a / in which case they're matched against the entire name.
268
269 What's Left To Do?
270 ~~~~~~~~~~~~~~~~~~
271
272 Nothing on this stuff.  When I get time I'd like to improve the interface
273 for reading messages with attachments.  It's my opinion that, because of the
274 command line nature of nmh, it makes the most sense to treat attachments as
275 separate messages.  In other words one should be able to read the next
276 attachment using next, and the previous one using prev.  One should be able
277 to show and scan attachments.  This would probably involve a major change
278 in the message numbering scheme to allow something like 123.4 to indicate
279 attachment 4 on message 123.
280
281         Jon Steinhart