]> diplodocus.org Git - nmh/blob - uip/inc.c
Bring these changes over from the branch.
[nmh] / uip / inc.c
1
2 /*
3 * inc.c -- incorporate messages from a maildrop into a folder
4 *
5 * $Id$
6 *
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
10 */
11
12 #ifdef MAILGROUP
13 /* Revised: Sat Apr 14 17:08:17 PDT 1990 (marvit@hplabs)
14 * Added hpux hacks to set and reset gid to be "mail" as needed. The reset
15 * is necessary so inc'ed mail is the group of the inc'er, rather than
16 * "mail". We setgid to egid only when [un]locking the mail file. This
17 * is also a major security precaution which will not be explained here.
18 *
19 * Fri Feb 7 16:04:57 PST 1992 John Romine <bug-mh@ics.uci.edu>
20 * NB: I'm not 100% sure that this setgid stuff is secure even now.
21 *
22 * See the *GROUPPRIVS() macros later. I'm reasonably happy with the setgid
23 * attribute. Running setuid root is probably not a terribly good idea, though.
24 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 04/1998
25 *
26 * Peter Maydell's patch slightly modified for nmh 0.28-pre2.
27 * Ruud de Rooij <ruud@debian.org> Wed, 22 Jul 1998 13:24:22 +0200
28 */
29 #endif
30
31 #include <h/mh.h>
32 #include <fcntl.h>
33
34 #ifdef POP
35 # include <h/dropsbr.h>
36 # include <h/popsbr.h>
37 #endif
38
39 #ifdef HESIOD
40 # include <hesiod.h>
41 #endif
42
43 #include <h/fmt_scan.h>
44 #include <h/scansbr.h>
45 #include <h/signals.h>
46 #include <h/tws.h>
47 #include <h/mts.h>
48 #include <errno.h>
49 #include <signal.h>
50
51 #ifndef POP
52 # define POPminc(a) (a)
53 #else
54 # define POPminc(a) 0
55 #endif
56
57 #ifndef RPOP
58 # define RPOPminc(a) (a)
59 #else
60 # define RPOPminc(a) 0
61 #endif
62
63 #ifndef APOP
64 # define APOPminc(a) (a)
65 #else
66 # define APOPminc(a) 0
67 #endif
68
69 #ifndef KPOP
70 # define KPOPminc(a) (a)
71 #else
72 # define KPOPminc(a) 0
73 #endif
74
75 #ifndef CYRUS_SASL
76 # define SASLminc(a) (a)
77 #else
78 # define SASLminc(a) 0
79 #endif
80
81 static struct swit switches[] = {
82 #define AUDSW 0
83 { "audit audit-file", 0 },
84 #define NAUDSW 1
85 { "noaudit", 0 },
86 #define CHGSW 2
87 { "changecur", 0 },
88 #define NCHGSW 3
89 { "nochangecur", 0 },
90 #define FILESW 4
91 { "file name", 0 },
92 #define FORMSW 5
93 { "form formatfile", 0 },
94 #define FMTSW 6
95 { "format string", 5 },
96 #define HOSTSW 7
97 { "host hostname", POPminc (-4) },
98 #define USERSW 8
99 { "user username", POPminc (-4) },
100 #define PACKSW 9
101 { "pack file", POPminc (-4) },
102 #define NPACKSW 10
103 { "nopack", POPminc (-6) },
104 #define APOPSW 11
105 { "apop", APOPminc (-4) },
106 #define NAPOPSW 12
107 { "noapop", APOPminc (-6) },
108 #define RPOPSW 13
109 { "rpop", RPOPminc (-4) },
110 #define NRPOPSW 14
111 { "norpop", RPOPminc (-6) },
112 #define SILSW 15
113 { "silent", 0 },
114 #define NSILSW 16
115 { "nosilent", 0 },
116 #define TRNCSW 17
117 { "truncate", 0 },
118 #define NTRNCSW 18
119 { "notruncate", 0 },
120 #define WIDTHSW 19
121 { "width columns", 0 },
122 #define VERSIONSW 20
123 { "version", 0 },
124 #define HELPSW 21
125 { "help", 0 },
126 #define SNOOPSW 22
127 { "snoop", -5 },
128 #define KPOPSW 23
129 { "kpop", KPOPminc (-4) },
130 #define SASLSW 24
131 { "sasl", SASLminc(-4) },
132 #define SASLMECHSW 25
133 { "saslmech", SASLminc(-8) },
134 { NULL, 0 }
135 };
136
137 extern int errno;
138
139 /*
140 * flags for the mail source
141 */
142 #define INC_FILE 0
143 #define INC_POP 1
144
145 static int inc_type;
146 static int snoop = 0;
147
148 #ifdef POP
149 extern char response[];
150
151 static char *packfile = NULL;
152 static int size;
153 static long pos;
154 static long start;
155 static long stop;
156
157 static int mbx_style = MMDF_FORMAT;
158 static int pd = NOTOK;
159 static FILE *pf = NULL;
160 #endif /* POP */
161
162 /* This is an attempt to simplify things by putting all the
163 * privilege ops into macros.
164 * *GROUPPRIVS() is related to handling the setgid MAIL property,
165 * and only applies if MAILGROUP is defined.
166 * *USERPRIVS() is related to handling the setuid root property,
167 * and only applies if POP is defined [why does POP => setuid root?]
168 * Basically, SAVEGROUPPRIVS() is called right at the top of main()
169 * to initialise things, and then DROPGROUPPRIVS() and GETGROUPPRIVS()
170 * do the obvious thing. TRYDROPGROUPPRIVS() has to be safe to call
171 * before DROPUSERPRIVS() is called [this is needed because setgid()
172 * sets both effective and real uids if euid is root.]
173 *
174 * There's probably a better implementation if we're allowed to use
175 * BSD-style setreuid() rather than using POSIX saved-ids.
176 * Anyway, if you're euid root it's a bit pointless to drop the group
177 * permissions...
178 *
179 * I'm pretty happy that the security is good provided we aren't setuid root.
180 * The only things we trust with group=mail privilege are lkfopen()
181 * and lkfclose().
182 */
183
184 /*
185 * For setting and returning to "mail" gid
186 */
187 #ifdef MAILGROUP
188 static int return_gid;
189 #ifndef POP
190 /* easy case; we're not setuid root, so can drop group privs
191 * immediately.
192 */
193 #define TRYDROPGROUPPRIVS() DROPGROUPPRIVS()
194 #else /* POP ie we are setuid root */
195 #define TRYDROPGROUPPRIVS() \
196 if (geteuid() != 0) DROPGROUPPRIVS()
197 #endif
198 #define DROPGROUPPRIVS() setgid(getgid())
199 #define GETGROUPPRIVS() setgid(return_gid)
200 #define SAVEGROUPPRIVS() return_gid = getegid()
201 #else
202 /* define *GROUPPRIVS() as null; this avoids having lots of "#ifdef MAILGROUP"s */
203 #define TRYDROPGROUPPRIVS()
204 #define DROPGROUPPRIVS()
205 #define GETGROUPPRIVS()
206 #define SAVEGROUPPRIVS()
207 #endif /* not MAILGROUP */
208
209 #ifdef POP
210 #define DROPUSERPRIVS() setuid(getuid())
211 #else
212 #define DROPUSERPRIVS()
213 #endif
214
215 /* these variables have to be globals so that done() can correctly clean up the lockfile */
216 static int locked = 0;
217 static char *newmail;
218 static FILE *in;
219
220 /*
221 * prototypes
222 */
223 char *map_name(char *);
224
225 #ifdef POP
226 int done(int);
227 static int pop_action(char *);
228 static int pop_pack(char *);
229 static int map_count(void);
230 #endif
231
232
233 int
234 main (int argc, char **argv)
235 {
236 int chgflag = 1, trnflag = 1;
237 int noisy = 1, width = 0;
238 int rpop, i, hghnum, msgnum;
239 int kpop = 0, sasl = 0;
240 char *cp, *maildir, *folder = NULL;
241 char *format = NULL, *form = NULL;
242 char *host = NULL, *user = NULL;
243 char *audfile = NULL, *from = NULL, *saslmech = NULL;
244 char buf[BUFSIZ], **argp, *nfs, **arguments;
245 struct msgs *mp;
246 struct stat st, s1;
247 FILE *aud = NULL;
248
249 #ifdef POP
250 int nmsgs, nbytes, p = 0;
251 char *pass = NULL;
252 char *MAILHOST_env_variable;
253 #endif
254
255 #ifdef MHE
256 FILE *mhe = NULL;
257 #endif
258
259 #ifdef HESIOD
260 struct hes_postoffice *po;
261 #endif
262
263 /* absolutely the first thing we do is save our privileges,
264 * and drop them if we can.
265 */
266 SAVEGROUPPRIVS();
267 TRYDROPGROUPPRIVS();
268
269 #ifdef LOCALE
270 setlocale(LC_ALL, "");
271 #endif
272 invo_name = r1bindex (argv[0], '/');
273
274 /* read user profile/context */
275 context_read();
276
277 mts_init (invo_name);
278 arguments = getarguments (invo_name, argc, argv, 1);
279 argp = arguments;
280
281 #ifdef POP
282 /*
283 * Scheme is:
284 * use MAILHOST environment variable if present,
285 * else try Hesiod.
286 * If that fails, use the default (if any)
287 * provided by mts.conf in mts_init()
288 */
289 if ((MAILHOST_env_variable = getenv("MAILHOST")) != NULL)
290 pophost = MAILHOST_env_variable;
291 # ifdef HESIOD
292 else if ((po = hes_getmailhost(getusername())) != NULL &&
293 strcmp(po->po_type, "POP") == 0)
294 pophost = po->po_host;
295 # endif /* HESIOD */
296 /*
297 * If there is a valid "pophost" entry in mts.conf,
298 * then use it as the default host.
299 */
300 if (pophost && *pophost)
301 host = pophost;
302
303 if ((cp = getenv ("MHPOPDEBUG")) && *cp)
304 snoop++;
305 #endif /* POP */
306
307 rpop = 0;
308
309 while ((cp = *argp++)) {
310 if (*cp == '-') {
311 switch (smatch (++cp, switches)) {
312 case AMBIGSW:
313 ambigsw (cp, switches);
314 done (1);
315 case UNKWNSW:
316 adios (NULL, "-%s unknown", cp);
317
318 case HELPSW:
319 snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name);
320 print_help (buf, switches, 1);
321 done (1);
322 case VERSIONSW:
323 print_version(invo_name);
324 done (1);
325
326 case AUDSW:
327 if (!(cp = *argp++) || *cp == '-')
328 adios (NULL, "missing argument to %s", argp[-2]);
329 audfile = getcpy (m_maildir (cp));
330 continue;
331 case NAUDSW:
332 audfile = NULL;
333 continue;
334
335 case CHGSW:
336 chgflag++;
337 continue;
338 case NCHGSW:
339 chgflag = 0;
340 continue;
341
342 /*
343 * The flag `trnflag' has the value:
344 *
345 * 2 if -truncate is given
346 * 1 by default (truncating is default)
347 * 0 if -notruncate is given
348 */
349 case TRNCSW:
350 trnflag = 2;
351 continue;
352 case NTRNCSW:
353 trnflag = 0;
354 continue;
355
356 case FILESW:
357 if (!(cp = *argp++) || *cp == '-')
358 adios (NULL, "missing argument to %s", argp[-2]);
359 from = path (cp, TFILE);
360
361 /*
362 * If the truncate file is in default state,
363 * change to not truncate.
364 */
365 if (trnflag == 1)
366 trnflag = 0;
367 continue;
368
369 case SILSW:
370 noisy = 0;
371 continue;
372 case NSILSW:
373 noisy++;
374 continue;
375
376 case FORMSW:
377 if (!(form = *argp++) || *form == '-')
378 adios (NULL, "missing argument to %s", argp[-2]);
379 format = NULL;
380 continue;
381 case FMTSW:
382 if (!(format = *argp++) || *format == '-')
383 adios (NULL, "missing argument to %s", argp[-2]);
384 form = NULL;
385 continue;
386
387 case WIDTHSW:
388 if (!(cp = *argp++) || *cp == '-')
389 adios (NULL, "missing argument to %s", argp[-2]);
390 width = atoi (cp);
391 continue;
392
393 case HOSTSW:
394 if (!(host = *argp++) || *host == '-')
395 adios (NULL, "missing argument to %s", argp[-2]);
396 continue;
397 case USERSW:
398 if (!(user = *argp++) || *user == '-')
399 adios (NULL, "missing argument to %s", argp[-2]);
400 continue;
401
402 case PACKSW:
403 #ifndef POP
404 if (!(cp = *argp++) || *cp == '-')
405 adios (NULL, "missing argument to %s", argp[-2]);
406 #else /* POP */
407 if (!(packfile = *argp++) || *packfile == '-')
408 adios (NULL, "missing argument to %s", argp[-2]);
409 #endif /* POP */
410 continue;
411 case NPACKSW:
412 #ifdef POP
413 packfile = NULL;
414 #endif /* POP */
415 continue;
416
417 case APOPSW:
418 rpop = -1;
419 continue;
420 case NAPOPSW:
421 rpop = 0;
422 continue;
423
424 case RPOPSW:
425 rpop = 1;
426 continue;
427 case NRPOPSW:
428 rpop = 0;
429 continue;
430
431 case KPOPSW:
432 kpop = 1;
433 continue;
434
435 case SNOOPSW:
436 snoop++;
437 continue;
438
439 case SASLSW:
440 sasl++;
441 continue;
442
443 case SASLMECHSW:
444 if (!(saslmech = *argp++) || *saslmech == '-')
445 adios (NULL, "missing argument to %s", argp[-2]);
446 continue;
447 }
448 }
449 if (*cp == '+' || *cp == '@') {
450 if (folder)
451 adios (NULL, "only one folder at a time!");
452 else
453 folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
454 } else {
455 adios (NULL, "usage: %s [+folder] [switches]", invo_name);
456 }
457 }
458
459 /* NOTE: above this point you should use TRYDROPGROUPPRIVS(),
460 * not DROPGROUPPRIVS().
461 */
462 #ifdef POP
463 if (host && !*host)
464 host = NULL;
465 if (from || !host || rpop <= 0)
466 DROPUSERPRIVS();
467 #endif /* POP */
468
469 /* guarantee dropping group priveleges; we might not have done so earlier */
470 DROPGROUPPRIVS();
471
472 /*
473 * Where are we getting the new mail?
474 */
475 if (from)
476 inc_type = INC_FILE;
477 #ifdef POP
478 else if (host)
479 inc_type = INC_POP;
480 #endif
481 else
482 inc_type = INC_FILE;
483
484 #ifdef POP
485 /*
486 * Are we getting the mail from
487 * a POP server?
488 */
489 if (inc_type == INC_POP) {
490 if (user == NULL)
491 user = getusername ();
492 if ( strcmp( POPSERVICE, "kpop" ) == 0 ) {
493 kpop = 1;
494 }
495 if (kpop || sasl || ( rpop > 0))
496 pass = getusername ();
497 else
498 ruserpass (host, &user, &pass);
499
500 /*
501 * initialize POP connection
502 */
503 if (pop_init (host, user, pass, snoop, kpop ? 1 : rpop, kpop,
504 sasl, saslmech) == NOTOK)
505 adios (NULL, "%s", response);
506
507 /* Check if there are any messages */
508 if (pop_stat (&nmsgs, &nbytes) == NOTOK)
509 adios (NULL, "%s", response);
510
511 if (rpop > 0)
512 DROPUSERPRIVS();
513 if (nmsgs == 0) {
514 pop_quit();
515 adios (NULL, "no mail to incorporate");
516 }
517 }
518 #endif /* POP */
519
520 /*
521 * We will get the mail from a file
522 * (typically the standard maildrop)
523 */
524
525 if (inc_type == INC_FILE) {
526 if (from)
527 newmail = from;
528 else if ((newmail = getenv ("MAILDROP")) && *newmail)
529 newmail = m_mailpath (newmail);
530 else if ((newmail = context_find ("maildrop")) && *newmail)
531 newmail = m_mailpath (newmail);
532 else {
533 newmail = concat (MAILDIR, "/", MAILFIL, NULL);
534 }
535 if (stat (newmail, &s1) == NOTOK || s1.st_size == 0)
536 adios (NULL, "no mail to incorporate");
537 }
538
539 #ifdef POP
540 /* skip the folder setup */
541 if ((inc_type == INC_POP) && packfile)
542 goto go_to_it;
543 #endif /* POP */
544
545 if (!context_find ("path"))
546 free (path ("./", TFOLDER));
547 if (!folder)
548 folder = getfolder (0);
549 maildir = m_maildir (folder);
550
551 if (stat (maildir, &st) == NOTOK) {
552 if (errno != ENOENT)
553 adios (maildir, "error on folder");
554 cp = concat ("Create folder \"", maildir, "\"? ", NULL);
555 if (noisy && !getanswer (cp))
556 done (1);
557 free (cp);
558 if (!makedir (maildir))
559 adios (NULL, "unable to create folder %s", maildir);
560 }
561
562 if (chdir (maildir) == NOTOK)
563 adios (maildir, "unable to change directory to");
564
565 /* read folder and create message structure */
566 if (!(mp = folder_read (folder)))
567 adios (NULL, "unable to read folder %s", folder);
568
569 #ifdef POP
570 go_to_it:
571 #endif /* POP */
572
573 if (inc_type == INC_FILE) {
574 if (access (newmail, W_OK) != NOTOK) {
575 locked++;
576 if (trnflag) {
577 SIGNAL (SIGHUP, SIG_IGN);
578 SIGNAL (SIGINT, SIG_IGN);
579 SIGNAL (SIGQUIT, SIG_IGN);
580 SIGNAL (SIGTERM, SIG_IGN);
581 }
582
583 GETGROUPPRIVS(); /* Reset gid to lock mail file */
584 in = lkfopen (newmail, "r");
585 DROPGROUPPRIVS();
586 if (in == NULL)
587 adios (NULL, "unable to lock and fopen %s", newmail);
588 fstat (fileno(in), &s1);
589 } else {
590 trnflag = 0;
591 if ((in = fopen (newmail, "r")) == NULL)
592 adios (newmail, "unable to read");
593 }
594 }
595
596 /* This shouldn't be necessary but it can't hurt. */
597 DROPGROUPPRIVS();
598
599 if (audfile) {
600 if ((i = stat (audfile, &st)) == NOTOK)
601 advise (NULL, "Creating Receive-Audit: %s", audfile);
602 if ((aud = fopen (audfile, "a")) == NULL)
603 adios (audfile, "unable to append to");
604 else if (i == NOTOK)
605 chmod (audfile, m_gmprot ());
606
607 #ifdef POP
608 fprintf (aud, from ? "<<inc>> %s -ms %s\n"
609 : host ? "<<inc>> %s -host %s -user %s%s\n"
610 : "<<inc>> %s\n",
611 dtimenow (0), from ? from : host, user,
612 rpop < 0 ? " -apop" : rpop > 0 ? " -rpop" : "");
613 #else /* POP */
614 fprintf (aud, from ? "<<inc>> %s -ms %s\n" : "<<inc>> %s\n",
615 dtimenow (0), from);
616 #endif /* POP */
617 }
618
619 #ifdef MHE
620 if (context_find ("mhe")) {
621 cp = concat (maildir, "/++", NULL);
622 i = stat (cp, &st);
623 if ((mhe = fopen (cp, "a")) == NULL)
624 admonish (cp, "unable to append to");
625 else
626 if (i == NOTOK)
627 chmod (cp, m_gmprot ());
628 free (cp);
629 }
630 #endif /* MHE */
631
632 /* Get new format string */
633 nfs = new_fs (form, format, FORMAT);
634
635 if (noisy) {
636 printf ("Incorporating new mail into %s...\n\n", folder);
637 fflush (stdout);
638 }
639
640 #ifdef POP
641 /*
642 * Get the mail from a POP server
643 */
644 if (inc_type == INC_POP) {
645 if (packfile) {
646 packfile = path (packfile, TFILE);
647 if (stat (packfile, &st) == NOTOK) {
648 if (errno != ENOENT)
649 adios (packfile, "error on file");
650 cp = concat ("Create file \"", packfile, "\"? ", NULL);
651 if (noisy && !getanswer (cp))
652 done (1);
653 free (cp);
654 }
655 msgnum = map_count ();
656 if ((pd = mbx_open (packfile, mbx_style, getuid(), getgid(), m_gmprot()))
657 == NOTOK)
658 adios (packfile, "unable to open");
659 if ((pf = fdopen (pd, "w+")) == NULL)
660 adios (NULL, "unable to fdopen %s", packfile);
661 } else {
662 hghnum = msgnum = mp->hghmsg;
663 /*
664 * Check if we have enough message space for all the new
665 * messages. If not, then realloc the folder and add enough
666 * space for all new messages plus 10 additional slots.
667 */
668 if (mp->hghmsg + nmsgs >= mp->hghoff
669 && !(mp = folder_realloc (mp, mp->lowoff, mp->hghmsg + nmsgs + 10)))
670 adios (NULL, "unable to allocate folder storage");
671 }
672
673 for (i = 1; i <= nmsgs; i++) {
674 msgnum++;
675 if (packfile) {
676 fseek (pf, 0L, SEEK_CUR);
677 pos = ftell (pf);
678 size = 0;
679 fwrite (mmdlm1, 1, strlen (mmdlm1), pf);
680 start = ftell (pf);
681
682 if (pop_retr (i, pop_pack) == NOTOK)
683 adios (NULL, "%s", response);
684
685 fseek (pf, 0L, SEEK_CUR);
686 stop = ftell (pf);
687 if (fflush (pf))
688 adios (packfile, "write error on");
689 fseek (pf, start, SEEK_SET);
690 } else {
691 cp = getcpy (m_name (msgnum));
692 if ((pf = fopen (cp, "w+")) == NULL)
693 adios (cp, "unable to write");
694 chmod (cp, m_gmprot ());
695 start = stop = 0L;
696
697 if (pop_retr (i, pop_action) == NOTOK)
698 adios (NULL, "%s", response);
699
700 if (fflush (pf))
701 adios (cp, "write error on");
702 fseek (pf, 0L, SEEK_SET);
703 }
704 switch (p = scan (pf, msgnum, 0, nfs, width,
705 packfile ? 0 : msgnum == mp->hghmsg + 1 && chgflag,
706 1, NULL, stop - start, noisy)) {
707 case SCNEOF:
708 printf ("%*d empty\n", DMAXFOLDER, msgnum);
709 break;
710
711 case SCNFAT:
712 trnflag = 0;
713 noisy++;
714 /* advise (cp, "unable to read"); already advised */
715 /* fall thru */
716
717 case SCNERR:
718 case SCNNUM:
719 break;
720
721 case SCNMSG:
722 case SCNENC:
723 default:
724 if (aud)
725 fputs (scanl, aud);
726 # ifdef MHE
727 if (mhe)
728 fputs (scanl, mhe);
729 # endif /* MHE */
730 if (noisy)
731 fflush (stdout);
732 if (!packfile) {
733 clear_msg_flags (mp, msgnum);
734 set_exists (mp, msgnum);
735 set_unseen (mp, msgnum);
736 mp->msgflags |= SEQMOD;
737 }
738 break;
739 }
740 if (packfile) {
741 fseek (pf, stop, SEEK_SET);
742 fwrite (mmdlm2, 1, strlen (mmdlm2), pf);
743 if (fflush (pf) || ferror (pf)) {
744 int e = errno;
745 pop_quit ();
746 errno = e;
747 adios (packfile, "write error on");
748 }
749 map_write (packfile, pd, 0, 0L, start, stop, pos, size, noisy);
750 } else {
751 if (ferror(pf) || fclose (pf)) {
752 int e = errno;
753 unlink (cp);
754 pop_quit ();
755 errno = e;
756 adios (cp, "write error on");
757 }
758 free (cp);
759 }
760
761 if (trnflag && pop_dele (i) == NOTOK)
762 adios (NULL, "%s", response);
763 }
764
765 if (pop_quit () == NOTOK)
766 adios (NULL, "%s", response);
767 if (packfile) {
768 mbx_close (packfile, pd);
769 pd = NOTOK;
770 }
771 }
772 #endif /* POP */
773
774 /*
775 * Get the mail from file (usually mail spool)
776 */
777 if (inc_type == INC_FILE) {
778 m_unknown (in); /* the MAGIC invocation... */
779 hghnum = msgnum = mp->hghmsg;
780 for (i = 0;;) {
781 /*
782 * Check if we need to allocate more space for message status.
783 * If so, then add space for an additional 100 messages.
784 */
785 if (msgnum >= mp->hghoff
786 && !(mp = folder_realloc (mp, mp->lowoff, mp->hghoff + 100))) {
787 advise (NULL, "unable to allocate folder storage");
788 i = NOTOK;
789 break;
790 }
791
792 #if 0
793 /* copy file from spool to tmp file */
794 tmpfilenam = m_scratch ("", invo_name);
795 if ((fd = creat (tmpfilenam, m_gmprot ())) == NOTOK)
796 adios (tmpfilenam, "unable to create");
797 chmod (tmpfilenam, m_gmprot ());
798 if (!(in2 = fdopen (fd, "r+")))
799 adios (tmpfilenam, "unable to access");
800 cpymsg (in, in2);
801
802 /* link message into folder */
803 newmsg = folder_addmsg(mp, tmpfilenam);
804 #endif
805
806 /* create scanline for new message */
807 switch (i = scan (in, msgnum + 1, msgnum + 1, nfs, width,
808 msgnum == hghnum && chgflag, 1, NULL, 0L, noisy)) {
809 case SCNFAT:
810 case SCNEOF:
811 break;
812
813 case SCNERR:
814 if (aud)
815 fputs ("inc aborted!\n", aud);
816 advise (NULL, "aborted!"); /* doesn't clean up locks! */
817 break;
818
819 case SCNNUM:
820 advise (NULL, "BUG in %s, number out of range", invo_name);
821 break;
822
823 default:
824 advise (NULL, "BUG in %s, scan() botch (%d)", invo_name, i);
825 break;
826
827 case SCNMSG:
828 case SCNENC:
829 if (aud)
830 fputs (scanl, aud);
831 #ifdef MHE
832 if (mhe)
833 fputs (scanl, mhe);
834 #endif /* MHE */
835 if (noisy)
836 fflush (stdout);
837
838 msgnum++;
839 mp->hghmsg++;
840 clear_msg_flags (mp, msgnum);
841 set_exists (mp, msgnum);
842 set_unseen (mp, msgnum);
843 mp->msgflags |= SEQMOD;
844 continue;
845 }
846 break;
847 }
848 }
849
850 #ifdef POP
851 if (p < 0) { /* error */
852 #else
853 if (i < 0) { /* error */
854 #endif
855 if (locked) {
856 GETGROUPPRIVS(); /* Be sure we can unlock mail file */
857 (void) lkfclose (in, newmail); in = NULL;
858 DROPGROUPPRIVS(); /* And then return us to normal privileges */
859 } else {
860 fclose (in); in = NULL;
861 }
862 adios (NULL, "failed");
863 }
864
865 if (aud)
866 fclose (aud);
867
868 #ifdef MHE
869 if (mhe)
870 fclose (mhe);
871 #endif /* MHE */
872
873 if (noisy)
874 fflush (stdout);
875
876 #ifdef POP
877 if ((inc_type == INC_POP) && packfile)
878 done (0);
879 #endif /* POP */
880
881 /*
882 * truncate file we are incorporating from
883 */
884 if (inc_type == INC_FILE) {
885 if (trnflag) {
886 if (stat (newmail, &st) != NOTOK && s1.st_mtime != st.st_mtime)
887 advise (NULL, "new messages have arrived!\007");
888 else {
889 if ((i = creat (newmail, 0600)) != NOTOK)
890 close (i);
891 else
892 admonish (newmail, "error zero'ing");
893 unlink(map_name(newmail));
894 }
895 } else {
896 if (noisy)
897 printf ("%s not zero'd\n", newmail);
898 }
899 }
900
901 if (msgnum == hghnum) {
902 admonish (NULL, "no messages incorporated");
903 } else {
904 context_replace (pfolder, folder); /* update current folder */
905 if (chgflag)
906 mp->curmsg = hghnum + 1;
907 mp->hghmsg = msgnum;
908 if (mp->lowmsg == 0)
909 mp->lowmsg = 1;
910 if (chgflag) /* sigh... */
911 seq_setcur (mp, mp->curmsg);
912 }
913
914 /*
915 * unlock the mail spool
916 */
917 if (inc_type == INC_FILE) {
918 if (locked) {
919 GETGROUPPRIVS(); /* Be sure we can unlock mail file */
920 (void) lkfclose (in, newmail); in = NULL;
921 DROPGROUPPRIVS(); /* And then return us to normal privileges */
922 } else {
923 fclose (in); in = NULL;
924 }
925 }
926
927 seq_setunseen (mp, 0); /* set the Unseen-Sequence */
928 seq_save (mp); /* synchronize sequences */
929 context_save (); /* save the context file */
930 return done (0);
931 }
932
933
934 #if 0
935
936 /*
937 * Copy message message from spool into
938 * temporary file. Massage the "From " line
939 * while copying.
940 */
941
942 cpymsg (FILE *in, FILE *out)
943 {
944 int state;
945 char *tmpbuf, name[NAMESZ];
946
947 for (;;) {
948 state = m_getfld (state, name, tmpbuf, rlwidth, in);
949 switch (state) {
950 case FLD:
951 case FLDPLUS:
952 break;
953 case BODY:
954 break;
955 case LENERR:
956 case FMTERR:
957 break;
958 case FILEEOF:
959 break;
960 default:
961 }
962 }
963 }
964 #endif /* if 0 */
965
966
967 int
968 done (int status)
969 {
970 #ifdef POP
971 if (packfile && pd != NOTOK)
972 mbx_close (packfile, pd);
973 #endif /* POP */
974 if (locked)
975 {
976 GETGROUPPRIVS();
977 lkfclose(in, newmail);
978 DROPGROUPPRIVS();
979 }
980 exit (status);
981 return 1; /* dead code to satisfy the compiler */
982 }
983
984 #ifdef POP
985 static int
986 pop_action (char *s)
987 {
988 fprintf (pf, "%s\n", s);
989 stop += strlen (s) + 1;
990 return 0; /* Is return value used? This was missing before 1999-07-15. */
991 }
992
993 static int
994 pop_pack (char *s)
995 {
996 int j;
997 char buffer[BUFSIZ];
998
999 snprintf (buffer, sizeof(buffer), "%s\n", s);
1000 for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++)
1001 continue;
1002 for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++)
1003 continue;
1004 fputs (buffer, pf);
1005 size += strlen (buffer) + 1;
1006 return 0; /* Is return value used? This was missing before 1999-07-15. */
1007 }
1008
1009 static int
1010 map_count (void)
1011 {
1012 int md;
1013 char *cp;
1014 struct drop d;
1015 struct stat st;
1016
1017 if (stat (packfile, &st) == NOTOK)
1018 return 0;
1019 if ((md = open (cp = map_name (packfile), O_RDONLY)) == NOTOK
1020 || map_chk (cp, md, &d, (long) st.st_size, 1)) {
1021 if (md != NOTOK)
1022 close (md);
1023 return 0;
1024 }
1025 close (md);
1026 return (d.d_id);
1027 }
1028 #endif /* POP */