0
|
1 /* sendsbr.c - routines to help WhatNow/Send along */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: sendsbr.c,v 1.1.1.1 2005/04/18 14:46:07 kono Exp $";
|
0
|
4 #endif /* lint */
|
|
5
|
|
6 #include "../h/mh.h"
|
|
7 #include <setjmp.h>
|
|
8 #include <stdio.h>
|
|
9 #include <signal.h>
|
|
10 #include <sys/types.h>
|
|
11 #include <sys/stat.h>
|
|
12 #ifdef UNISTD
|
|
13 #include <unistd.h>
|
|
14 #endif
|
12
|
15 extern char *LocalName();
|
0
|
16
|
|
17 static alert(), anno(), annoaux();
|
|
18 static int tmp_fd();
|
|
19 static int sendaux();
|
|
20 #ifdef MIME
|
|
21 static int sendaux2();
|
|
22 #endif
|
|
23
|
|
24 /* */
|
|
25
|
|
26 int debugsw = 0; /* global */
|
|
27 int forwsw = 1;
|
|
28 int inplace = 0;
|
|
29 int mime = 0;
|
|
30 int pushsw = 0;
|
|
31 int splitsw = -1;
|
|
32 int unique = 0;
|
|
33 int verbsw = 0;
|
|
34
|
|
35 char *altmsg = NULL; /* .. */
|
|
36 char *annotext = NULL;
|
|
37 char *distfile = NULL;
|
|
38
|
|
39
|
|
40 static int armed = 0;
|
|
41 static jmp_buf env;
|
|
42
|
|
43
|
|
44 char *getusr ();
|
|
45 off_t lseek ();
|
|
46 time_t time ();
|
|
47
|
|
48 /* */
|
|
49
|
|
50 int sendsbr (vec, vecp, drft, st)
|
|
51 char **vec,
|
|
52 *drft;
|
|
53 int vecp;
|
|
54 struct stat *st;
|
|
55 {
|
|
56 int status;
|
|
57
|
|
58 armed++;
|
|
59 switch (setjmp (env)) {
|
|
60 case OK:
|
|
61 status = sendaux (vec, vecp, drft, st) ? NOTOK : OK;
|
|
62 break;
|
|
63
|
|
64 default:
|
|
65 status = DONE;
|
|
66 break;
|
|
67 }
|
|
68 armed = 0;
|
|
69 if (distfile)
|
|
70 (void) unlink (distfile);
|
|
71
|
|
72 return status;
|
|
73 }
|
|
74
|
|
75 /* */
|
|
76
|
|
77 #ifdef MIME
|
|
78 #include "../h/mhn.h"
|
|
79
|
|
80 static int sendaux (vec, vecp, drft, st)
|
|
81 register char **vec,
|
|
82 *drft;
|
|
83 int vecp;
|
|
84 register struct stat *st;
|
|
85 {
|
|
86 int compnum,
|
|
87 nparts,
|
|
88 partno,
|
|
89 state,
|
|
90 status;
|
|
91 time_t clock;
|
|
92 long pos,
|
|
93 start;
|
|
94 char *cp,
|
|
95 *dp,
|
|
96 *subject = "",
|
|
97 buffer[BUFSIZ],
|
|
98 msgid[BUFSIZ],
|
|
99 name[NAMESZ],
|
|
100 partnum[BUFSIZ];
|
|
101 struct stat sts;
|
|
102 FILE *in;
|
|
103
|
|
104 if (splitsw < 0
|
|
105 || distfile
|
|
106 || stat (drft, &sts) == NOTOK
|
|
107 || sts.st_size < CPERMSG) {
|
|
108 one_shot: ;
|
|
109 splitsw = -1;
|
|
110 return sendaux2 (vec, vecp, drft, st);
|
|
111 }
|
|
112
|
|
113 if ((in = fopen (drft, "r")) == NULL)
|
|
114 adios (drft, "unable to open for reading");
|
|
115
|
|
116 cp = dp = NULL;
|
|
117 start = 0L;
|
|
118 for (compnum = 1, state = FLD;;) {
|
|
119 switch (state = m_getfld (state, name, buffer, sizeof buffer, in)) {
|
|
120 case FLD:
|
|
121 case FLDPLUS:
|
|
122 case FLDEOF:
|
|
123 compnum++;
|
|
124
|
|
125 if (uleq (name, "Message-ID")) {
|
|
126 while (state == FLDPLUS)
|
|
127 state = m_getfld (state, name, buffer, sizeof buffer,
|
|
128 in);
|
|
129 }
|
|
130 else
|
|
131 if (uprf (name, XXX_FIELD_PRF)
|
|
132 || uleq (name, VRSN_FIELD)
|
|
133 || uleq (name, "Encrypted")) {
|
|
134 dp = add (concat (name, ":", buffer, NULLCP), dp);
|
|
135 while (state == FLDPLUS) {
|
|
136 state = m_getfld (state, name, buffer,
|
|
137 sizeof buffer, in);
|
|
138 dp = add (buffer, dp);
|
|
139 }
|
|
140 } else if (uleq (name, "Subject")) {
|
|
141 long sublen;
|
|
142 char *pp;
|
|
143
|
|
144 subject = add (buffer, NULLCP);
|
|
145 while (state == FLDPLUS) {
|
|
146 state = m_getfld (state, name, buffer,
|
|
147 sizeof buffer, in);
|
|
148 subject = add (buffer, subject);
|
|
149 }
|
|
150 dp = add (concat (name, ":", subject, NULLCP), dp);
|
|
151 if ((sublen = strlen (subject)) > 0
|
|
152 && subject[sublen - 1] == '\n')
|
|
153 subject[sublen - 1] = '\0';
|
|
154 #ifdef MIME_HEADERS
|
|
155 if ((pp = rindex(subject, '\n')))
|
|
156 sublen = strlen(pp) - 1;
|
|
157 else {
|
|
158 pp = subject;
|
|
159 sublen += 8 /* strlen("Subject:") */;
|
|
160 }
|
|
161 if (sublen + 12 + 6 > CPERLIN && strstr(pp, "=?"))
|
|
162 subject = add ("\n\t", subject);
|
|
163 #endif /* MIME_HEADERS */
|
|
164 }
|
|
165 else {
|
|
166 cp = add (concat (name, ":", buffer, NULLCP), cp);
|
|
167 while (state == FLDPLUS) {
|
|
168 state = m_getfld (state, name, buffer,
|
|
169 sizeof buffer, in);
|
|
170 cp = add (buffer, cp);
|
|
171 }
|
|
172 }
|
|
173 if (state != FLDEOF) {
|
|
174 start = ftell (in) + 1;
|
|
175 continue;
|
|
176 }
|
|
177 /* else fall... */
|
|
178 case BODY:
|
|
179 case BODYEOF:
|
|
180 case FILEEOF:
|
|
181 break;
|
|
182
|
|
183 case LENERR:
|
|
184 case FMTERR:
|
|
185 adios (NULLCP, "message format error in component #%d",
|
|
186 compnum);
|
|
187
|
|
188 default:
|
|
189 adios (NULLCP, "getfld () returned %d", state);
|
|
190 }
|
|
191
|
|
192 break;
|
|
193 }
|
|
194 if (cp == NULL)
|
|
195 adios (NULLCP, "headers missing from draft");
|
|
196
|
|
197 nparts = 1, pos = start;
|
|
198 while (fgets (buffer, sizeof buffer - 1, in)) {
|
|
199 register long len;
|
|
200
|
|
201 if ((pos += (len = strlen (buffer))) > CPERMSG)
|
|
202 nparts++, pos = len;
|
|
203 }
|
|
204 if (nparts == 1) {
|
|
205 free (cp);
|
|
206 if (dp)
|
|
207 free (dp);
|
|
208
|
|
209 (void) fclose (in);
|
|
210
|
|
211 goto one_shot;
|
|
212 }
|
|
213
|
|
214 if (!pushsw) {
|
|
215 printf ("Sending as %d Partial Messages\n", nparts);
|
|
216 (void) fflush (stdout);
|
|
217 }
|
|
218 status = OK;
|
|
219
|
|
220 vec[vecp++] = "-partno";
|
|
221 vec[vecp++] = partnum;
|
|
222 if (splitsw == 0)
|
|
223 vec[vecp++] = "-queued";
|
|
224
|
|
225 (void) time (&clock);
|
|
226 (void) sprintf (msgid, "<%d.%ld@%s>", getpid (), (long)clock, LocalName ());
|
|
227
|
|
228 (void) fseek (in, start, 0);
|
|
229 for (partno = 1; partno <= nparts; partno++) {
|
|
230 char tmpdrf[BUFSIZ];
|
|
231 FILE *out;
|
|
232
|
|
233 (void) strcpy (tmpdrf, m_scratch (drft, invo_name));
|
|
234 if ((out = fopen (tmpdrf, "w")) == NULL)
|
|
235 adios (tmpdrf, "unable to open for writing");
|
|
236 (void) chmod (tmpdrf, 0600);
|
|
237
|
|
238 (void) fputs (cp, out);
|
|
239 fprintf (out, "Subject:%s (part %d of %d)\n",
|
|
240 subject, partno, nparts);
|
|
241 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
|
|
242 fprintf (out,
|
|
243 "%s: message/partial; id=\"%s\";\n\tnumber=%d; total=%d\n",
|
|
244 TYPE_FIELD, msgid, partno, nparts);
|
|
245 fprintf (out, "%s: part %d of %d\n\n", DESCR_FIELD, partno,
|
|
246 nparts);
|
|
247
|
|
248 if (partno == 1) {
|
|
249 if (dp)
|
|
250 (void) fputs (dp, out);
|
|
251 fprintf (out, "Message-ID: %s\n", msgid);
|
|
252 fprintf (out, "\n");
|
|
253 }
|
|
254
|
|
255 pos = 0;
|
|
256 for (;;) {
|
|
257 register long len;
|
|
258
|
|
259 if (!fgets (buffer, sizeof buffer - 1, in)) {
|
|
260 if (partno == nparts)
|
|
261 break;
|
|
262 adios (NULLCP, "premature eof");
|
|
263 }
|
|
264
|
|
265 if ((pos += (len = strlen (buffer))) > CPERMSG) {
|
|
266 (void) fseek (in, -len, 1);
|
|
267 break;
|
|
268 }
|
|
269
|
|
270 (void) fputs (buffer, out);
|
|
271 }
|
|
272
|
|
273 if (fflush (out))
|
|
274 adios (tmpdrf, "error writing to");
|
|
275
|
|
276 (void) fclose (out);
|
|
277
|
|
278 if (!pushsw && verbsw) {
|
|
279 printf ("\n");
|
|
280 (void) fflush (stdout);
|
|
281 }
|
|
282 if (splitsw > 0 && 1 < partno && partno <= nparts) {
|
|
283 if (!pushsw) {
|
|
284 printf ("pausing %d seconds before sending part %d...\n",
|
|
285 splitsw, partno);
|
|
286 (void) fflush (stdout);
|
|
287 }
|
|
288
|
|
289 sleep ((unsigned) splitsw);
|
|
290 }
|
|
291
|
|
292 (void) sprintf (partnum, "%d", partno);
|
|
293 status = sendaux2 (vec, vecp, tmpdrf, st);
|
|
294 (void) unlink (tmpdrf);
|
|
295 if (status != OK)
|
|
296 break;
|
|
297
|
|
298 annotext = NULL;
|
|
299 }
|
|
300
|
|
301 free (cp);
|
|
302 if (dp)
|
|
303 free (dp);
|
|
304
|
|
305 (void) fclose (in);
|
|
306
|
|
307 if (status == OK &&
|
|
308 rename (drft, strcpy (buffer, m_backup (drft))) == NOTOK)
|
|
309 advise (buffer, "unable to rename %s to", drft);
|
|
310
|
|
311 return status;
|
|
312 }
|
|
313 #endif
|
|
314
|
|
315 /* */
|
|
316
|
|
317 #ifndef MIME
|
|
318 static int sendaux (vec, vecp, drft, st)
|
|
319 #else /* MIME */
|
|
320 static int sendaux2 (vec, vecp, drft, st)
|
|
321 #endif /* MIME */
|
|
322 register char **vec,
|
|
323 *drft;
|
|
324 int vecp;
|
|
325 register struct stat *st;
|
|
326 {
|
|
327 int child_id,
|
|
328 i,
|
|
329 status,
|
|
330 fd,
|
|
331 fd2;
|
|
332 #ifdef MH_PLUS
|
|
333 register char *cp;
|
|
334 #endif /* MH_PLUS */
|
|
335 char backup[BUFSIZ],
|
|
336 buf[BUFSIZ],
|
|
337 file[BUFSIZ];
|
|
338
|
|
339 fd = pushsw ? tmp_fd () : NOTOK;
|
|
340 fd2 = NOTOK;
|
|
341
|
|
342 #ifdef MH_PLUS
|
|
343 if ((cp = m_find("sendername"))) {
|
|
344 vec[vecp++] = "-user";
|
|
345 vec[vecp++] = cp;
|
|
346 }
|
|
347 if ((cp = m_find("from-address"))) {
|
|
348 vec[vecp++] = "-from";
|
|
349 vec[vecp++] = cp;
|
|
350 }
|
|
351 #endif /* MH_PLUS */
|
|
352
|
|
353 if (pushsw && unique) {
|
|
354 if (rename (drft, strcpy (file, m_scratch (drft, invo_name)))
|
|
355 == NOTOK)
|
|
356 adios (file, "unable to rename %s to", drft);
|
|
357 drft = file;
|
|
358 }
|
|
359 vec[vecp++] = drft;
|
|
360 if (annotext)
|
|
361 if ((fd2 = tmp_fd ()) != NOTOK) {
|
|
362 vec[vecp++] = "-idanno";
|
|
363 (void) sprintf (buf, "%d", fd2);
|
|
364 vec[vecp++] = buf;
|
|
365 }
|
|
366 else
|
|
367 admonish (NULLCP, "unable to create file for annotation list");
|
|
368 if (distfile && distout (drft, distfile, backup) == NOTOK)
|
|
369 done (1);
|
|
370 vec[vecp] = NULL;
|
|
371
|
|
372 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
|
|
373 sleep (5);
|
|
374 switch (child_id) {
|
|
375 case NOTOK: /* oops */
|
|
376 adios ("fork", "unable to");
|
|
377
|
|
378 case OK: /* send it */
|
|
379 if (fd != NOTOK) {
|
|
380 (void) dup2 (fd, fileno (stdout));
|
|
381 (void) dup2 (fd, fileno (stderr));
|
|
382 (void) close (fd);
|
|
383 }
|
|
384 execvp (postproc, vec);
|
|
385 fprintf (stderr, "unable to exec ");
|
|
386 perror (postproc);
|
|
387 _exit (-1);
|
|
388
|
|
389 default: /* wait for it */
|
|
390 if ((status = pidwait (child_id, NOTOK)) == 0) {
|
|
391 if (annotext && fd2 != NOTOK)
|
|
392 anno (fd2, st);
|
|
393 if (splitsw < 0
|
|
394 && rename (drft, strcpy (buf, m_backup (drft)))
|
|
395 == NOTOK)
|
|
396 advise (buf, "unable to rename %s to", drft);
|
|
397 }
|
|
398 else {
|
|
399 if (fd != NOTOK) {
|
|
400 alert (drft, fd);
|
|
401 (void) close (fd);
|
|
402 }
|
|
403 else
|
|
404 advise (NULLCP, "message not delivered to anyone");
|
|
405 if (annotext && fd2 != NOTOK)
|
|
406 (void) close (fd2);
|
|
407 if (distfile) {
|
|
408 (void) unlink (drft);
|
|
409 if (rename (backup, drft) == NOTOK)
|
|
410 advise (drft, "unable to rename %s to", backup);
|
|
411 }
|
|
412 }
|
|
413 break;
|
|
414 }
|
|
415
|
|
416 return status;
|
|
417 }
|
|
418
|
|
419 /* */
|
|
420
|
|
421 static alert (file, out)
|
|
422 register char *file;
|
|
423 int out;
|
|
424 {
|
|
425 int child_id,
|
|
426 i,
|
|
427 in;
|
|
428 char buf[BUFSIZ];
|
|
429
|
|
430 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
|
|
431 sleep (5);
|
|
432 switch (child_id) {
|
|
433 case NOTOK: /* oops */
|
|
434 advise ("fork", "unable to");
|
|
435
|
|
436 case OK: /* send it */
|
|
437 (void) signal (SIGHUP, SIG_IGN);
|
|
438 (void) signal (SIGINT, SIG_IGN);
|
|
439 (void) signal (SIGQUIT, SIG_IGN);
|
|
440 (void) signal (SIGTERM, SIG_IGN);
|
|
441 if (forwsw)
|
|
442 if ((in = open (file, 0)) == NOTOK)
|
|
443 admonish (file, "unable to re-open");
|
|
444 else {
|
|
445 (void) lseek (out, (off_t)0, 2);
|
|
446 (void) strcpy (buf, "\nMessage not delivered to anyone.\n");
|
|
447 (void) write (out, buf, strlen (buf));
|
|
448 (void) strcpy (buf, "\n------- Unsent Draft\n\n");
|
|
449 (void) write (out, buf, strlen (buf));
|
|
450 cpydgst (in, out, file, "temporary file");
|
|
451 (void) close (in);
|
|
452 (void) strcpy (buf, "\n------- End of Unsent Draft\n");
|
|
453 (void) write (out, buf, strlen (buf));
|
|
454 if (rename (file, strcpy (buf, m_backup (file))) == NOTOK)
|
|
455 admonish (buf, "unable to rename %s to", file);
|
|
456 }
|
|
457 (void) lseek (out, (off_t)0, 0);
|
|
458 (void) dup2 (out, fileno (stdin));
|
|
459 (void) close (out);
|
|
460 (void) sprintf (buf, "send failed on %s",
|
|
461 forwsw ? "enclosed draft" : file);
|
|
462
|
|
463 execlp (mailproc, r1bindex (mailproc, '/'), getusr (),
|
|
464 "-subject", buf, NULLCP);
|
|
465 fprintf (stderr, "unable to exec ");
|
|
466 perror (mailproc);
|
|
467 _exit (-1);
|
|
468
|
|
469 default: /* no waiting... */
|
|
470 break;
|
|
471 }
|
|
472 }
|
|
473
|
|
474 /* */
|
|
475
|
|
476 static int tmp_fd () {
|
|
477 int fd;
|
|
478 char tmpfil[BUFSIZ];
|
|
479
|
|
480 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
481 if ((fd = creat (tmpfil, 0600)) == NOTOK)
|
|
482 return NOTOK;
|
|
483 (void) close (fd);
|
|
484
|
|
485 if ((fd = open (tmpfil, 2)) == NOTOK)
|
|
486 return NOTOK;
|
|
487 if (debugsw)
|
|
488 advise (NULLCP, "temporary file %s selected", tmpfil);
|
|
489 else
|
|
490 if (unlink (tmpfil) == NOTOK)
|
|
491 advise (tmpfil, "unable to remove");
|
|
492
|
|
493 return fd;
|
|
494 }
|
|
495
|
|
496 /* */
|
|
497
|
|
498 static anno (fd, st)
|
|
499 int fd;
|
|
500 register struct stat *st;
|
|
501 {
|
|
502 int child_id;
|
|
503 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
|
|
504 static char *cwd = NULL;
|
|
505 struct stat st2;
|
|
506
|
|
507 if (altmsg &&
|
|
508 (stat (altmsg, &st2) == NOTOK
|
|
509 || st -> st_mtime != st2.st_mtime
|
|
510 || st -> st_dev != st2.st_dev
|
|
511 || st -> st_ino != st2.st_ino)) {
|
|
512 if (debugsw)
|
|
513 admonish (NULLCP, "$mhaltmsg mismatch");
|
|
514 return;
|
|
515 }
|
|
516
|
|
517 child_id = debugsw ? NOTOK : fork ();
|
|
518 switch (child_id) {
|
|
519 case NOTOK: /* oops */
|
|
520 if (!debugsw)
|
|
521 advise (NULLCP,
|
|
522 "unable to fork, so doing annotations by hand...");
|
|
523 if (cwd == NULL)
|
|
524 cwd = getcpy (pwd ());
|
|
525
|
|
526 case OK:
|
|
527 hstat = signal (SIGHUP, SIG_IGN);
|
|
528 istat = signal (SIGINT, SIG_IGN);
|
|
529 qstat = signal (SIGQUIT, SIG_IGN);
|
|
530 tstat = signal (SIGTERM, SIG_IGN);
|
|
531
|
|
532 annoaux (fd);
|
|
533 if (child_id == OK)
|
|
534 _exit (0);
|
|
535
|
|
536 (void) signal (SIGHUP, hstat);
|
|
537 (void) signal (SIGINT, istat);
|
|
538 (void) signal (SIGQUIT, qstat);
|
|
539 (void) signal (SIGTERM, tstat);
|
|
540
|
|
541 (void) chdir (cwd);
|
|
542 break;
|
|
543
|
|
544 default: /* no waiting... */
|
|
545 (void) close (fd);
|
|
546 break;
|
|
547 }
|
|
548 }
|
|
549
|
|
550 /* */
|
|
551
|
|
552 static annoaux (fd)
|
|
553 int fd;
|
|
554 {
|
|
555 int fd2,
|
|
556 fd3,
|
|
557 msgnum;
|
|
558 char *cp,
|
|
559 *folder,
|
|
560 *maildir,
|
|
561 buffer[BUFSIZ],
|
|
562 **ap;
|
|
563 FILE *fp;
|
|
564 struct msgs *mp;
|
|
565
|
|
566 if ((folder = getenv ("mhfolder")) == NULL || *folder == 0) {
|
|
567 if (debugsw)
|
|
568 admonish (NULLCP, "$mhfolder not set");
|
|
569 return;
|
|
570 }
|
|
571 maildir = m_maildir (folder);
|
|
572 if (chdir (maildir) == NOTOK) {
|
|
573 if (debugsw)
|
|
574 admonish (maildir, "unable to change directory to");
|
|
575 return;
|
|
576 }
|
|
577 if (!(mp = m_gmsg (folder))) {
|
|
578 if (debugsw)
|
|
579 admonish (NULLCP, "unable to read folder %s");
|
|
580 return;
|
|
581 }
|
|
582 if (mp -> hghmsg == 0) {
|
|
583 if (debugsw)
|
|
584 admonish (NULLCP, "no messages in %s", folder);
|
|
585 goto oops;
|
|
586 }
|
|
587
|
|
588 if ((cp = getenv ("mhmessages")) == NULL || *cp == 0) {
|
|
589 if (debugsw)
|
|
590 admonish (NULLCP, "$mhmessages not set");
|
|
591 goto oops;
|
|
592 }
|
|
593 if (!debugsw /* MOBY HACK... */
|
|
594 && pushsw
|
|
595 && (fd3 = open ("/dev/null", 2)) != NOTOK
|
|
596 && (fd2 = dup (fileno (stderr))) != NOTOK) {
|
|
597 (void) dup2 (fd3, fileno (stderr));
|
|
598 (void) close (fd3);
|
|
599 }
|
|
600 else
|
|
601 fd2 = NOTOK;
|
|
602 for (ap = brkstring (cp = getcpy (cp), " ", NULLCP); *ap; ap++)
|
|
603 (void) m_convert (mp, *ap);
|
|
604 free (cp);
|
|
605 if (fd2 != NOTOK)
|
|
606 (void) dup2 (fd2, fileno (stderr));
|
|
607 if (mp -> numsel == 0) {
|
|
608 if (debugsw)
|
|
609 admonish (NULLCP, "no messages to annotate");
|
|
610 goto oops;
|
|
611 }
|
|
612
|
|
613 (void) lseek (fd, (off_t)0, 0);
|
|
614 if ((fp = fdopen (fd, "r")) == NULL) {
|
|
615 if (debugsw)
|
|
616 admonish (NULLCP, "unable to fdopen annotation list");
|
|
617 goto oops;
|
|
618 }
|
|
619 cp = NULL;
|
|
620 while (fgets (buffer, sizeof buffer, fp) != NULL)
|
|
621 cp = add (buffer, cp);
|
|
622 (void) fclose (fp);
|
|
623
|
|
624 if (debugsw)
|
|
625 advise (NULLCP, "annotate%s with %s: \"%s\"",
|
|
626 inplace ? " inplace" : "", annotext, cp);
|
|
627 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
628 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
629 if (debugsw)
|
|
630 advise (NULLCP, "annotate message %d", msgnum);
|
|
631 (void) annotate (m_name (msgnum), annotext, cp, inplace, 1);
|
|
632 }
|
|
633
|
|
634 free (cp);
|
|
635
|
|
636 oops: ;
|
|
637 m_fmsg (mp);
|
|
638 }
|
|
639
|
|
640 /* */
|
|
641
|
|
642 void done (status)
|
|
643 int status;
|
|
644 {
|
|
645 if (armed)
|
|
646 longjmp (env, status ? status : NOTOK);
|
|
647
|
|
648 exit (status);
|
|
649 }
|