Deleted Added
full compact
mail.local.c (71348) mail.local.c (73191)
1/*
1/*
2 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
2 * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1990, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13#ifndef lint
14static char copyright[] =
3 * All rights reserved.
4 * Copyright (c) 1990, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13#ifndef lint
14static char copyright[] =
15"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\
15"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
16 All rights reserved.\n\
17 Copyright (c) 1990, 1993, 1994\n\
18 The Regents of the University of California. All rights reserved.\n";
19#endif /* ! lint */
20
21#ifndef lint
16 All rights reserved.\n\
17 Copyright (c) 1990, 1993, 1994\n\
18 The Regents of the University of California. All rights reserved.\n";
19#endif /* ! lint */
20
21#ifndef lint
22static char id[] = "@(#)$Id: mail.local.c,v 8.143.4.39 2000/11/14 20:02:47 gshapiro Exp $";
22static char id[] = "@(#)$Id: mail.local.c,v 8.143.4.57 2001/02/11 20:08:20 gshapiro Exp $";
23#endif /* ! lint */
24
23#endif /* ! lint */
24
25/* $FreeBSD: head/contrib/sendmail/mail.local/mail.local.c 71348 2001-01-21 22:21:43Z gshapiro $ */
25/* $FreeBSD: head/contrib/sendmail/mail.local/mail.local.c 73191 2001-02-28 00:22:47Z gshapiro $ */
26
27/*
28** This is not intended to work on System V derived systems
29** such as Solaris or HP-UX, since they use a totally different
30** approach to mailboxes (essentially, they have a setgid program
31** rather than setuid, and they rely on the ability to "give away"
32** files to do their work). IT IS NOT A BUG that this doesn't
33** work on such architectures.

--- 69 unchanged lines hidden (view full) ---

103# define USE_LOCKF 1
104# define HASSNPRINTF 1
105# define _PATH_MAILDIR "/var/mail"
106# endif /* NCR_MP_RAS3 */
107
108# if defined(_AIX)
109# define USE_LOCKF 1
110# define USE_SETEUID 1
26
27/*
28** This is not intended to work on System V derived systems
29** such as Solaris or HP-UX, since they use a totally different
30** approach to mailboxes (essentially, they have a setgid program
31** rather than setuid, and they rely on the ability to "give away"
32** files to do their work). IT IS NOT A BUG that this doesn't
33** work on such architectures.

--- 69 unchanged lines hidden (view full) ---

103# define USE_LOCKF 1
104# define HASSNPRINTF 1
105# define _PATH_MAILDIR "/var/mail"
106# endif /* NCR_MP_RAS3 */
107
108# if defined(_AIX)
109# define USE_LOCKF 1
110# define USE_SETEUID 1
111# define USE_VSYSLOG 0
112# endif /* defined(_AIX) */
113
114# if defined(__hpux)
115# define USE_LOCKF 1
116# define USE_SETRESUID 1
111# endif /* defined(_AIX) */
112
113# if defined(__hpux)
114# define USE_LOCKF 1
115# define USE_SETRESUID 1
117# define USE_VSYSLOG 0
118# endif /* defined(__hpux) */
119
120# ifdef DGUX
121# define HASSNPRINTF 1
122# define USE_LOCKF 1
116# endif /* defined(__hpux) */
117
118# ifdef DGUX
119# define HASSNPRINTF 1
120# define USE_LOCKF 1
123# define USE_VSYSLOG 0
124# endif /* DGUX */
125
126# if defined(_CRAY)
127# if !defined(MAXPATHLEN)
128# define MAXPATHLEN PATHSIZE
129# endif /* !defined(MAXPATHLEN) */
121# endif /* DGUX */
122
123# if defined(_CRAY)
124# if !defined(MAXPATHLEN)
125# define MAXPATHLEN PATHSIZE
126# endif /* !defined(MAXPATHLEN) */
130# define USE_VSYSLOG 0
131# define _PATH_MAILDIR "/usr/spool/mail"
132# endif /* defined(_CRAY) */
133
127# define _PATH_MAILDIR "/usr/spool/mail"
128# endif /* defined(_CRAY) */
129
134# if defined(ultrix)
135# define USE_VSYSLOG 0
136# endif /* defined(ultrix) */
137
138# if defined(__osf__)
139# define USE_VSYSLOG 0
140# endif /* defined(__osf__) */
141
142# if defined(NeXT) && !defined(__APPLE__)
143# include <libc.h>
144# define _PATH_MAILDIR "/usr/spool/mail"
145# define S_IRUSR S_IREAD
146# define S_IWUSR S_IWRITE
147# endif /* defined(NeXT) && !defined(__APPLE__) */
148
149# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6)

--- 7 unchanged lines hidden (view full) ---

157# ifdef USE_LOCKF
158# define flock(a, b) lockf(a, b, 0)
159# ifdef LOCK_EX
160# undef LOCK_EX
161# endif /* LOCK_EX */
162# define LOCK_EX F_LOCK
163# endif /* USE_LOCKF */
164
130# if defined(NeXT) && !defined(__APPLE__)
131# include <libc.h>
132# define _PATH_MAILDIR "/usr/spool/mail"
133# define S_IRUSR S_IREAD
134# define S_IWUSR S_IWRITE
135# endif /* defined(NeXT) && !defined(__APPLE__) */
136
137# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6)

--- 7 unchanged lines hidden (view full) ---

145# ifdef USE_LOCKF
146# define flock(a, b) lockf(a, b, 0)
147# ifdef LOCK_EX
148# undef LOCK_EX
149# endif /* LOCK_EX */
150# define LOCK_EX F_LOCK
151# endif /* USE_LOCKF */
152
165# ifndef USE_VSYSLOG
166# define USE_VSYSLOG 1
167# endif /* ! USE_VSYSLOG */
168
169# ifndef LOCK_EX
170# include <sys/file.h>
171# endif /* ! LOCK_EX */
172
173# if defined(BSD4_4) || defined(__GLIBC__)
174# include <paths.h>
175# define _PATH_LOCTMP "/var/tmp/local.XXXXXX"
176# endif /* defined(BSD4_4) || defined(__GLIBC__) */

--- 25 unchanged lines hidden (view full) ---

202# ifdef HPUX11
203# define HASSNPRINTF 1 /* has snprintf starting in 11.X */
204# endif /* HPUX11 */
205
206# if _AIX4 >= 40300
207# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */
208# endif /* _AIX4 >= 40300 */
209
153# ifndef LOCK_EX
154# include <sys/file.h>
155# endif /* ! LOCK_EX */
156
157# if defined(BSD4_4) || defined(__GLIBC__)
158# include <paths.h>
159# define _PATH_LOCTMP "/var/tmp/local.XXXXXX"
160# endif /* defined(BSD4_4) || defined(__GLIBC__) */

--- 25 unchanged lines hidden (view full) ---

186# ifdef HPUX11
187# define HASSNPRINTF 1 /* has snprintf starting in 11.X */
188# endif /* HPUX11 */
189
190# if _AIX4 >= 40300
191# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */
192# endif /* _AIX4 >= 40300 */
193
210# if !HASSNPRINTF
194# if !HASSNPRINTF && !SFIO
211extern int snprintf __P((char *, size_t, const char *, ...));
212# ifndef _CRAY
213extern int vsnprintf __P((char *, size_t, const char *, ...));
214# endif /* ! _CRAY */
195extern int snprintf __P((char *, size_t, const char *, ...));
196# ifndef _CRAY
197extern int vsnprintf __P((char *, size_t, const char *, ...));
198# endif /* ! _CRAY */
215# endif /* !HASSNPRINTF */
199# endif /* !HASSNPRINTF && !SFIO */
216
217/*
218** If you don't have setreuid, and you have saved uids, and you have
219** a seteuid() call that doesn't try to emulate using setuid(), then
220** you can try defining USE_SETEUID.
221*/
200
201/*
202** If you don't have setreuid, and you have saved uids, and you have
203** a seteuid() call that doesn't try to emulate using setuid(), then
204** you can try defining USE_SETEUID.
205*/
206
222# ifdef USE_SETEUID
223# define setreuid(r, e) seteuid(e)
224# endif /* USE_SETEUID */
225
226/*
227** And of course on hpux you have setresuid()
228*/
207# ifdef USE_SETEUID
208# define setreuid(r, e) seteuid(e)
209# endif /* USE_SETEUID */
210
211/*
212** And of course on hpux you have setresuid()
213*/
214
229# ifdef USE_SETRESUID
230# define setreuid(r, e) setresuid(-1, e, -1)
231# endif /* USE_SETRESUID */
232
233# ifndef _PATH_LOCTMP
234# define _PATH_LOCTMP "/var/tmp/local.XXXXXX"
235# endif /* ! _PATH_LOCTMP */
236# ifndef _PATH_MAILDIR

--- 21 unchanged lines hidden (view full) ---

258
259#ifdef CONTENTLENGTH
260char ContentHdr[40] = "Content-Length: ";
261off_t HeaderLength;
262off_t BodyLength;
263#endif /* CONTENTLENGTH */
264
265bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */
215# ifdef USE_SETRESUID
216# define setreuid(r, e) setresuid(-1, e, -1)
217# endif /* USE_SETRESUID */
218
219# ifndef _PATH_LOCTMP
220# define _PATH_LOCTMP "/var/tmp/local.XXXXXX"
221# endif /* ! _PATH_LOCTMP */
222# ifndef _PATH_MAILDIR

--- 21 unchanged lines hidden (view full) ---

244
245#ifdef CONTENTLENGTH
246char ContentHdr[40] = "Content-Length: ";
247off_t HeaderLength;
248off_t BodyLength;
249#endif /* CONTENTLENGTH */
250
251bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */
252char ErrBuf[10240]; /* error buffer */
266int ExitVal = EX_OK; /* sysexits.h error value. */
253int ExitVal = EX_OK; /* sysexits.h error value. */
254bool HoldErrs = FALSE; /* Hold errors in ErrBuf */
267bool LMTPMode = FALSE;
255bool LMTPMode = FALSE;
268bool bouncequota = FALSE; /* permanent error when over quota */
256bool BounceQuota = FALSE; /* permanent error when over quota */
269bool nobiff = FALSE;
270bool nofsync = FALSE;
271
257bool nobiff = FALSE;
258bool nofsync = FALSE;
259
272void deliver __P((int, char *, bool));
260void deliver __P((int, char *));
273int e_to_sys __P((int));
274void notifybiff __P((char *));
261int e_to_sys __P((int));
262void notifybiff __P((char *));
275int store __P((char *, int));
263int store __P((char *, int, bool *));
276void usage __P((void));
264void usage __P((void));
277void vwarn __P((const char *, _BSD_VA_LIST_));
278int lockmbox __P((char *));
279void unlockmbox __P((void));
280void mailerr __P((const char *, const char *, ...));
265int lockmbox __P((char *));
266void unlockmbox __P((void));
267void mailerr __P((const char *, const char *, ...));
268void flush_error __P((void));
281
282
283int
284main(argc, argv)
285 int argc;
286 char *argv[];
287{
288 struct passwd *pw;
289 int ch, fd;
290 uid_t uid;
291 char *from;
292 extern char *optarg;
293 extern int optind;
269
270
271int
272main(argc, argv)
273 int argc;
274 char *argv[];
275{
276 struct passwd *pw;
277 int ch, fd;
278 uid_t uid;
279 char *from;
280 extern char *optarg;
281 extern int optind;
294 extern void dolmtp __P((bool));
295
296
297 /* make sure we have some open file descriptors */
298 for (fd = 10; fd < 30; fd++)
299 (void) close(fd);
300
301 /* use a reasonable umask */
302 (void) umask(0077);

--- 13 unchanged lines hidden (view full) ---

316 EightBitMime = FALSE;
317 break;
318
319 case 'B':
320 nobiff = TRUE;
321 break;
322
323 case 'b': /* bounce mail when over quota. */
282
283
284 /* make sure we have some open file descriptors */
285 for (fd = 10; fd < 30; fd++)
286 (void) close(fd);
287
288 /* use a reasonable umask */
289 (void) umask(0077);

--- 13 unchanged lines hidden (view full) ---

303 EightBitMime = FALSE;
304 break;
305
306 case 'B':
307 nobiff = TRUE;
308 break;
309
310 case 'b': /* bounce mail when over quota. */
324 bouncequota = TRUE;
311 BounceQuota = TRUE;
325 break;
326
327 case 'd': /* Backward compatible. */
328 break;
329
330 case 'f':
331 case 'r': /* Backward compatible. */
332 if (from != NULL)
333 {
312 break;
313
314 case 'd': /* Backward compatible. */
315 break;
316
317 case 'f':
318 case 'r': /* Backward compatible. */
319 if (from != NULL)
320 {
334 mailerr(NULL, "multiple -f options");
321 mailerr(NULL, "Multiple -f options");
335 usage();
336 }
337 from = optarg;
338 break;
339
340 case 'l':
341 LMTPMode = TRUE;
342 break;

--- 10 unchanged lines hidden (view full) ---

353 argc -= optind;
354 argv += optind;
355
356 /* initialize biff structures */
357 if (!nobiff)
358 notifybiff(NULL);
359
360 if (LMTPMode)
322 usage();
323 }
324 from = optarg;
325 break;
326
327 case 'l':
328 LMTPMode = TRUE;
329 break;

--- 10 unchanged lines hidden (view full) ---

340 argc -= optind;
341 argv += optind;
342
343 /* initialize biff structures */
344 if (!nobiff)
345 notifybiff(NULL);
346
347 if (LMTPMode)
361 dolmtp(bouncequota);
348 {
349 extern void dolmtp __P((void));
362
350
351 if (argc > 0)
352 {
353 mailerr("421", "Users should not be specified in command line if LMTP required");
354 exit(EX_TEMPFAIL);
355 }
356
357 dolmtp();
358 /* NOTREACHED */
359 exit(EX_OK);
360 }
361
362 /* Non-LMTP from here on out */
363 if (*argv == '\0')
364 usage();
365
366 /*
367 ** If from not specified, use the name from getlogin() if the
368 ** uid matches, otherwise, use the name from the password file
369 ** corresponding to the uid.
370 */
363 if (*argv == '\0')
364 usage();
365
366 /*
367 ** If from not specified, use the name from getlogin() if the
368 ** uid matches, otherwise, use the name from the password file
369 ** corresponding to the uid.
370 */
371
371 uid = getuid();
372
373 if (from == NULL && ((from = getlogin()) == NULL ||
374 (pw = getpwnam(from)) == NULL ||
375 pw->pw_uid != uid))
376 from = (pw = getpwuid(uid)) != NULL ? pw->pw_name : "???";
377
378 /*
379 ** There is no way to distinguish the error status of one delivery
380 ** from the rest of the deliveries. So, if we failed hard on one
381 ** or more deliveries, but had no failures on any of the others, we
382 ** return a hard failure. If we failed temporarily on one or more
383 ** deliveries, we return a temporary failure regardless of the other
384 ** failures. This results in the delivery being reattempted later
385 ** at the expense of repeated failures and multiple deliveries.
386 */
372 uid = getuid();
373
374 if (from == NULL && ((from = getlogin()) == NULL ||
375 (pw = getpwnam(from)) == NULL ||
376 pw->pw_uid != uid))
377 from = (pw = getpwuid(uid)) != NULL ? pw->pw_name : "???";
378
379 /*
380 ** There is no way to distinguish the error status of one delivery
381 ** from the rest of the deliveries. So, if we failed hard on one
382 ** or more deliveries, but had no failures on any of the others, we
383 ** return a hard failure. If we failed temporarily on one or more
384 ** deliveries, we return a temporary failure regardless of the other
385 ** failures. This results in the delivery being reattempted later
386 ** at the expense of repeated failures and multiple deliveries.
387 */
387 for (fd = store(from, 0); *argv; ++argv)
388 deliver(fd, *argv, bouncequota);
388
389 HoldErrs = TRUE;
390 fd = store(from, 0, NULL);
391 HoldErrs = FALSE;
392 if (fd < 0)
393 {
394 flush_error();
395 exit(ExitVal);
396 }
397 for (; *argv != NULL; ++argv)
398 deliver(fd, *argv);
389 exit(ExitVal);
390 /* NOTREACHED */
391 return ExitVal;
392}
393
394char *
395parseaddr(s, rcpt)
396 char *s;

--- 71 unchanged lines hidden (view full) ---

468
469 if (*s == '\0')
470 s = MAILER_DAEMON;
471
472 l = strlen(s) + 1;
473 p = malloc(l);
474 if (p == NULL)
475 {
399 exit(ExitVal);
400 /* NOTREACHED */
401 return ExitVal;
402}
403
404char *
405parseaddr(s, rcpt)
406 char *s;

--- 71 unchanged lines hidden (view full) ---

478
479 if (*s == '\0')
480 s = MAILER_DAEMON;
481
482 l = strlen(s) + 1;
483 p = malloc(l);
484 if (p == NULL)
485 {
476 printf("421 4.3.0 memory exhausted\r\n");
486 mailerr("421 4.3.0", "Memory exhausted");
477 exit(EX_TEMPFAIL);
478 }
479
480 (void) strlcpy(p, s, l);
481 return p;
482}
483
484char *
485process_recipient(addr)
486 char *addr;
487{
488 if (getpwnam(addr) == NULL)
487 exit(EX_TEMPFAIL);
488 }
489
490 (void) strlcpy(p, s, l);
491 return p;
492}
493
494char *
495process_recipient(addr)
496 char *addr;
497{
498 if (getpwnam(addr) == NULL)
489 return "550 5.1.1 user unknown";
499 return "550 5.1.1 User unknown";
490 return NULL;
491}
492
493#define RCPT_GROW 30
494
495void
500 return NULL;
501}
502
503#define RCPT_GROW 30
504
505void
496dolmtp(bouncequota)
497 bool bouncequota;
506dolmtp()
498{
499 char *return_path = NULL;
500 char **rcpt_addr = NULL;
501 int rcpt_num = 0;
502 int rcpt_alloc = 0;
503 bool gotlhlo = FALSE;
504 char *err;
505 int msgfd;
506 char *p;
507 int i;
508 char myhostname[1024];
509 char buf[4096];
510
507{
508 char *return_path = NULL;
509 char **rcpt_addr = NULL;
510 int rcpt_num = 0;
511 int rcpt_alloc = 0;
512 bool gotlhlo = FALSE;
513 char *err;
514 int msgfd;
515 char *p;
516 int i;
517 char myhostname[1024];
518 char buf[4096];
519
520 memset(myhostname, '\0', sizeof myhostname);
511 (void) gethostname(myhostname, sizeof myhostname - 1);
521 (void) gethostname(myhostname, sizeof myhostname - 1);
522 if (myhostname[0] == '\0')
523 strlcpy(myhostname, "localhost", sizeof myhostname);
512
513 printf("220 %s LMTP ready\r\n", myhostname);
514 for (;;)
515 {
516 (void) fflush(stdout);
517 if (fgets(buf, sizeof(buf) - 1, stdin) == NULL)
518 exit(EX_OK);
519 p = buf + strlen(buf) - 1;
520 if (p >= buf && *p == '\n')
521 *p-- = '\0';
522 if (p >= buf && *p == '\r')
523 *p-- = '\0';
524
525 switch (buf[0])
526 {
527 case 'd':
528 case 'D':
529 if (strcasecmp(buf, "data") == 0)
530 {
524
525 printf("220 %s LMTP ready\r\n", myhostname);
526 for (;;)
527 {
528 (void) fflush(stdout);
529 if (fgets(buf, sizeof(buf) - 1, stdin) == NULL)
530 exit(EX_OK);
531 p = buf + strlen(buf) - 1;
532 if (p >= buf && *p == '\n')
533 *p-- = '\0';
534 if (p >= buf && *p == '\r')
535 *p-- = '\0';
536
537 switch (buf[0])
538 {
539 case 'd':
540 case 'D':
541 if (strcasecmp(buf, "data") == 0)
542 {
543 bool inbody = FALSE;
544
531 if (rcpt_num == 0)
532 {
545 if (rcpt_num == 0)
546 {
533 printf("503 5.5.1 No recipients\r\n");
547 mailerr("503 5.5.1", "No recipients");
534 continue;
535 }
548 continue;
549 }
536 msgfd = store(return_path, rcpt_num);
537 if (msgfd == -1)
550 HoldErrs = TRUE;
551 msgfd = store(return_path, rcpt_num, &inbody);
552 HoldErrs = FALSE;
553 if (msgfd < 0 && !inbody)
554 {
555 flush_error();
538 continue;
556 continue;
557 }
539
540 for (i = 0; i < rcpt_num; i++)
541 {
558
559 for (i = 0; i < rcpt_num; i++)
560 {
561 if (msgfd < 0)
562 {
563 /* print error for rcpt */
564 flush_error();
565 continue;
566 }
542 p = strchr(rcpt_addr[i], '+');
543 if (p != NULL)
567 p = strchr(rcpt_addr[i], '+');
568 if (p != NULL)
544 *p++ = '\0';
545 deliver(msgfd, rcpt_addr[i],
546 bouncequota);
569 *p = '\0';
570 deliver(msgfd, rcpt_addr[i]);
547 }
571 }
548 (void) close(msgfd);
572 if (msgfd >= 0)
573 (void) close(msgfd);
549 goto rset;
550 }
551 goto syntaxerr;
552 /* NOTREACHED */
553 break;
554
555 case 'l':
556 case 'L':
557 if (strncasecmp(buf, "lhlo ", 5) == 0)
558 {
559 /* check for duplicate per RFC 1651 4.2 */
560 if (gotlhlo)
561 {
574 goto rset;
575 }
576 goto syntaxerr;
577 /* NOTREACHED */
578 break;
579
580 case 'l':
581 case 'L':
582 if (strncasecmp(buf, "lhlo ", 5) == 0)
583 {
584 /* check for duplicate per RFC 1651 4.2 */
585 if (gotlhlo)
586 {
562 printf("503 %s Duplicate LHLO\r\n",
587 mailerr("503", "%s Duplicate LHLO",
563 myhostname);
564 continue;
565 }
566 gotlhlo = TRUE;
567 printf("250-%s\r\n", myhostname);
568 if (EightBitMime)
569 printf("250-8BITMIME\r\n");
570 printf("250-ENHANCEDSTATUSCODES\r\n");

--- 5 unchanged lines hidden (view full) ---

576 break;
577
578 case 'm':
579 case 'M':
580 if (strncasecmp(buf, "mail ", 5) == 0)
581 {
582 if (return_path != NULL)
583 {
588 myhostname);
589 continue;
590 }
591 gotlhlo = TRUE;
592 printf("250-%s\r\n", myhostname);
593 if (EightBitMime)
594 printf("250-8BITMIME\r\n");
595 printf("250-ENHANCEDSTATUSCODES\r\n");

--- 5 unchanged lines hidden (view full) ---

601 break;
602
603 case 'm':
604 case 'M':
605 if (strncasecmp(buf, "mail ", 5) == 0)
606 {
607 if (return_path != NULL)
608 {
584 printf("503 5.5.1 Nested MAIL command\r\n");
609 mailerr("503 5.5.1",
610 "Nested MAIL command");
585 continue;
586 }
587 if (strncasecmp(buf+5, "from:", 5) != 0 ||
588 ((return_path = parseaddr(buf + 10,
589 FALSE)) == NULL))
590 {
611 continue;
612 }
613 if (strncasecmp(buf+5, "from:", 5) != 0 ||
614 ((return_path = parseaddr(buf + 10,
615 FALSE)) == NULL))
616 {
591 printf("501 5.5.4 Syntax error in parameters\r\n");
617 mailerr("501 5.5.4",
618 "Syntax error in parameters");
592 continue;
593 }
619 continue;
620 }
594 printf("250 2.5.0 ok\r\n");
621 printf("250 2.5.0 Ok\r\n");
595 continue;
596 }
597 goto syntaxerr;
598 /* NOTREACHED */
599 break;
600
601 case 'n':
602 case 'N':
603 if (strcasecmp(buf, "noop") == 0)
604 {
622 continue;
623 }
624 goto syntaxerr;
625 /* NOTREACHED */
626 break;
627
628 case 'n':
629 case 'N':
630 if (strcasecmp(buf, "noop") == 0)
631 {
605 printf("250 2.0.0 ok\r\n");
632 printf("250 2.0.0 Ok\r\n");
606 continue;
607 }
608 goto syntaxerr;
609 /* NOTREACHED */
610 break;
611
612 case 'q':
613 case 'Q':
614 if (strcasecmp(buf, "quit") == 0)
615 {
633 continue;
634 }
635 goto syntaxerr;
636 /* NOTREACHED */
637 break;
638
639 case 'q':
640 case 'Q':
641 if (strcasecmp(buf, "quit") == 0)
642 {
616 printf("221 2.0.0 bye\r\n");
643 printf("221 2.0.0 Bye\r\n");
617 exit(EX_OK);
618 }
619 goto syntaxerr;
620 /* NOTREACHED */
621 break;
622
623 case 'r':
624 case 'R':
625 if (strncasecmp(buf, "rcpt ", 5) == 0)
626 {
627 if (return_path == NULL)
628 {
644 exit(EX_OK);
645 }
646 goto syntaxerr;
647 /* NOTREACHED */
648 break;
649
650 case 'r':
651 case 'R':
652 if (strncasecmp(buf, "rcpt ", 5) == 0)
653 {
654 if (return_path == NULL)
655 {
629 printf("503 5.5.1 Need MAIL command\r\n");
656 mailerr("503 5.5.1",
657 "Need MAIL command");
630 continue;
631 }
632 if (rcpt_num >= rcpt_alloc)
633 {
634 rcpt_alloc += RCPT_GROW;
635 rcpt_addr = (char **)
636 REALLOC((char *) rcpt_addr,
637 rcpt_alloc *
638 sizeof(char **));
639 if (rcpt_addr == NULL)
640 {
658 continue;
659 }
660 if (rcpt_num >= rcpt_alloc)
661 {
662 rcpt_alloc += RCPT_GROW;
663 rcpt_addr = (char **)
664 REALLOC((char *) rcpt_addr,
665 rcpt_alloc *
666 sizeof(char **));
667 if (rcpt_addr == NULL)
668 {
641 printf("421 4.3.0 memory exhausted\r\n");
669 mailerr("421 4.3.0",
670 "Memory exhausted");
642 exit(EX_TEMPFAIL);
643 }
644 }
645 if (strncasecmp(buf + 5, "to:", 3) != 0 ||
646 ((rcpt_addr[rcpt_num] = parseaddr(buf + 8,
647 TRUE)) == NULL))
648 {
671 exit(EX_TEMPFAIL);
672 }
673 }
674 if (strncasecmp(buf + 5, "to:", 3) != 0 ||
675 ((rcpt_addr[rcpt_num] = parseaddr(buf + 8,
676 TRUE)) == NULL))
677 {
649 printf("501 5.5.4 Syntax error in parameters\r\n");
678 mailerr("501 5.5.4",
679 "Syntax error in parameters");
650 continue;
651 }
680 continue;
681 }
652 if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL)
682 err = process_recipient(rcpt_addr[rcpt_num]);
683 if (err != NULL)
653 {
684 {
654 printf("%s\r\n", err);
685 mailerr(NULL, "%s", err);
655 continue;
656 }
657 rcpt_num++;
686 continue;
687 }
688 rcpt_num++;
658 printf("250 2.1.5 ok\r\n");
689 printf("250 2.1.5 Ok\r\n");
659 continue;
660 }
661 else if (strcasecmp(buf, "rset") == 0)
662 {
690 continue;
691 }
692 else if (strcasecmp(buf, "rset") == 0)
693 {
663 printf("250 2.0.0 ok\r\n");
694 printf("250 2.0.0 Ok\r\n");
664
665rset:
666 while (rcpt_num > 0)
667 free(rcpt_addr[--rcpt_num]);
668 if (return_path != NULL)
669 free(return_path);
670 return_path = NULL;
671 continue;
672 }
673 goto syntaxerr;
674 /* NOTREACHED */
675 break;
676
677 case 'v':
678 case 'V':
679 if (strncasecmp(buf, "vrfy ", 5) == 0)
680 {
695
696rset:
697 while (rcpt_num > 0)
698 free(rcpt_addr[--rcpt_num]);
699 if (return_path != NULL)
700 free(return_path);
701 return_path = NULL;
702 continue;
703 }
704 goto syntaxerr;
705 /* NOTREACHED */
706 break;
707
708 case 'v':
709 case 'V':
710 if (strncasecmp(buf, "vrfy ", 5) == 0)
711 {
681 printf("252 2.3.3 try RCPT to attempt delivery\r\n");
712 printf("252 2.3.3 Try RCPT to attempt delivery\r\n");
682 continue;
683 }
684 goto syntaxerr;
685 /* NOTREACHED */
686 break;
687
688 default:
689 syntaxerr:
713 continue;
714 }
715 goto syntaxerr;
716 /* NOTREACHED */
717 break;
718
719 default:
720 syntaxerr:
690 printf("500 5.5.2 Syntax error\r\n");
721 mailerr("500 5.5.2", "Syntax error");
691 continue;
692 /* NOTREACHED */
693 break;
694 }
695 }
696}
697
698int
722 continue;
723 /* NOTREACHED */
724 break;
725 }
726 }
727}
728
729int
699store(from, lmtprcpts)
730store(from, lmtprcpts, inbody)
700 char *from;
701 int lmtprcpts;
731 char *from;
732 int lmtprcpts;
733 bool *inbody;
702{
703 FILE *fp = NULL;
704 time_t tval;
705 bool eline;
706 bool fullline = TRUE; /* current line is terminated */
707 bool prevfl; /* previous line was terminated */
708 char line[2048];
709 int fd;
710 char tmpbuf[sizeof _PATH_LOCTMP + 1];
711
734{
735 FILE *fp = NULL;
736 time_t tval;
737 bool eline;
738 bool fullline = TRUE; /* current line is terminated */
739 bool prevfl; /* previous line was terminated */
740 char line[2048];
741 int fd;
742 char tmpbuf[sizeof _PATH_LOCTMP + 1];
743
744 if (inbody != NULL)
745 *inbody = FALSE;
746
712 (void) umask(0077);
713 (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf);
747 (void) umask(0077);
748 (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf);
714 if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL)
749 if ((fd = mkstemp(tmpbuf)) < 0 || (fp = fdopen(fd, "w+")) == NULL)
715 {
750 {
716 if (lmtprcpts)
717 {
718 printf("451 4.3.0 unable to open temporary file\r\n");
719 return -1;
720 }
721 else
722 {
723 mailerr("451 4.3.0", "unable to open temporary file");
724 exit(ExitVal);
725 }
751 mailerr("451 4.3.0", "Unable to open temporary file");
752 return -1;
726 }
727 (void) unlink(tmpbuf);
728
729 if (LMTPMode)
730 {
753 }
754 (void) unlink(tmpbuf);
755
756 if (LMTPMode)
757 {
731 printf("354 go ahead\r\n");
758 printf("354 Go ahead\r\n");
732 (void) fflush(stdout);
733 }
759 (void) fflush(stdout);
760 }
761 if (inbody != NULL)
762 *inbody = TRUE;
734
735 (void) time(&tval);
736 (void) fprintf(fp, "From %s %s", from, ctime(&tval));
737
738#ifdef CONTENTLENGTH
739 HeaderLength = 0;
740 BodyLength = -1;
741#endif /* CONTENTLENGTH */
742
743 line[0] = '\0';
744 eline = TRUE;
763
764 (void) time(&tval);
765 (void) fprintf(fp, "From %s %s", from, ctime(&tval));
766
767#ifdef CONTENTLENGTH
768 HeaderLength = 0;
769 BodyLength = -1;
770#endif /* CONTENTLENGTH */
771
772 line[0] = '\0';
773 eline = TRUE;
745 while (fgets(line, sizeof(line), stdin) != (char *)NULL)
774 while (fgets(line, sizeof(line), stdin) != (char *) NULL)
746 {
747 size_t line_len = 0;
748 int peek;
749
750 prevfl = fullline; /* preserve state of previous line */
751 while (line[line_len] != '\n' && line_len < sizeof(line) - 2)
752 line_len++;
753 line_len++;
754
755 /* Check for dot-stuffing */
775 {
776 size_t line_len = 0;
777 int peek;
778
779 prevfl = fullline; /* preserve state of previous line */
780 while (line[line_len] != '\n' && line_len < sizeof(line) - 2)
781 line_len++;
782 line_len++;
783
784 /* Check for dot-stuffing */
756 if (prevfl && lmtprcpts && line[0] == '.')
785 if (prevfl && LMTPMode && line[0] == '.')
757 {
758 if (line[1] == '\n' ||
759 (line[1] == '\r' && line[2] == '\n'))
760 goto lmtpdot;
761 memcpy(line, line + 1, line_len);
762 line_len--;
763 }
764

--- 27 unchanged lines hidden (view full) ---

792 }
793 else
794 fullline = TRUE;
795
796#ifdef CONTENTLENGTH
797 if (prevfl && line[0] == '\n' && HeaderLength == 0)
798 {
799 eline = FALSE;
786 {
787 if (line[1] == '\n' ||
788 (line[1] == '\r' && line[2] == '\n'))
789 goto lmtpdot;
790 memcpy(line, line + 1, line_len);
791 line_len--;
792 }
793

--- 27 unchanged lines hidden (view full) ---

821 }
822 else
823 fullline = TRUE;
824
825#ifdef CONTENTLENGTH
826 if (prevfl && line[0] == '\n' && HeaderLength == 0)
827 {
828 eline = FALSE;
800 HeaderLength = ftell(fp);
829 if (fp != NULL)
830 HeaderLength = ftell(fp);
801 if (HeaderLength <= 0)
802 {
803 /*
804 ** shouldn't happen, unless ftell() is
805 ** badly broken
806 */
807
808 HeaderLength = -1;
809 }
810 }
811#else /* CONTENTLENGTH */
812 if (prevfl && line[0] == '\n')
813 eline = TRUE;
814#endif /* CONTENTLENGTH */
815 else
816 {
817 if (eline && line[0] == 'F' &&
831 if (HeaderLength <= 0)
832 {
833 /*
834 ** shouldn't happen, unless ftell() is
835 ** badly broken
836 */
837
838 HeaderLength = -1;
839 }
840 }
841#else /* CONTENTLENGTH */
842 if (prevfl && line[0] == '\n')
843 eline = TRUE;
844#endif /* CONTENTLENGTH */
845 else
846 {
847 if (eline && line[0] == 'F' &&
848 fp != NULL &&
818 !memcmp(line, "From ", 5))
819 (void) putc('>', fp);
820 eline = FALSE;
821#ifdef CONTENTLENGTH
822 /* discard existing "Content-Length:" headers */
823 if (prevfl && HeaderLength == 0 &&
824 (line[0] == 'C' || line[0] == 'c') &&
825 strncasecmp(line, ContentHdr, 15) == 0)
826 {
827 /*
828 ** be paranoid: clear the line
829 ** so no "wrong matches" may occur later
830 */
831 line[0] = '\0';
832 continue;
833 }
834#endif /* CONTENTLENGTH */
835
836 }
849 !memcmp(line, "From ", 5))
850 (void) putc('>', fp);
851 eline = FALSE;
852#ifdef CONTENTLENGTH
853 /* discard existing "Content-Length:" headers */
854 if (prevfl && HeaderLength == 0 &&
855 (line[0] == 'C' || line[0] == 'c') &&
856 strncasecmp(line, ContentHdr, 15) == 0)
857 {
858 /*
859 ** be paranoid: clear the line
860 ** so no "wrong matches" may occur later
861 */
862 line[0] = '\0';
863 continue;
864 }
865#endif /* CONTENTLENGTH */
866
867 }
837 (void) fwrite(line, sizeof(char), line_len, fp);
838 if (ferror(fp))
868 if (fp != NULL)
839 {
869 {
840 if (lmtprcpts)
870 (void) fwrite(line, sizeof(char), line_len, fp);
871 if (ferror(fp))
841 {
872 {
842 while (lmtprcpts--)
843 printf("451 4.3.0 temporary file write error\r\n");
844 (void) fclose(fp);
845 return -1;
846 }
847 else
848 {
849 mailerr("451 4.3.0",
873 mailerr("451 4.3.0",
850 "temporary file write error");
874 "Temporary file write error");
851 (void) fclose(fp);
875 (void) fclose(fp);
852 exit(ExitVal);
876 fp = NULL;
877 continue;
853 }
854 }
855 }
856
878 }
879 }
880 }
881
857 if (lmtprcpts)
882 /* check if an error occurred */
883 if (fp == NULL)
884 return -1;
885
886 if (LMTPMode)
858 {
859 /* Got a premature EOF -- toss message and exit */
860 exit(EX_OK);
861 }
862
863 /* If message not newline terminated, need an extra. */
887 {
888 /* Got a premature EOF -- toss message and exit */
889 exit(EX_OK);
890 }
891
892 /* If message not newline terminated, need an extra. */
864 if (strchr(line, '\n') == NULL)
893 if (fp != NULL && strchr(line, '\n') == NULL)
865 (void) putc('\n', fp);
866
867 lmtpdot:
868
869#ifdef CONTENTLENGTH
894 (void) putc('\n', fp);
895
896 lmtpdot:
897
898#ifdef CONTENTLENGTH
870 BodyLength = ftell(fp);
899 if (fp != NULL)
900 BodyLength = ftell(fp);
871 if (HeaderLength == 0 && BodyLength > 0) /* empty body */
872 {
873 HeaderLength = BodyLength;
874 BodyLength = 0;
875 }
876 else
877 BodyLength = BodyLength - HeaderLength - 1 ;
878

--- 9 unchanged lines hidden (view full) ---

888 (long) BodyLength);
889 strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16);
890 }
891 else
892 BodyLength = -1; /* Something is wrong here */
893#endif /* CONTENTLENGTH */
894
895 /* Output a newline; note, empty messages are allowed. */
901 if (HeaderLength == 0 && BodyLength > 0) /* empty body */
902 {
903 HeaderLength = BodyLength;
904 BodyLength = 0;
905 }
906 else
907 BodyLength = BodyLength - HeaderLength - 1 ;
908

--- 9 unchanged lines hidden (view full) ---

918 (long) BodyLength);
919 strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16);
920 }
921 else
922 BodyLength = -1; /* Something is wrong here */
923#endif /* CONTENTLENGTH */
924
925 /* Output a newline; note, empty messages are allowed. */
896 (void) putc('\n', fp);
926 if (fp != NULL)
927 (void) putc('\n', fp);
897
928
898 if (fflush(fp) == EOF || ferror(fp) != 0)
929 if (fp == NULL || fflush(fp) == EOF || ferror(fp) != 0)
899 {
930 {
900 if (lmtprcpts)
901 {
902 while (lmtprcpts--)
903 printf("451 4.3.0 temporary file write error\r\n");
931 mailerr("451 4.3.0", "Temporary file write error");
932 if (fp != NULL)
904 (void) fclose(fp);
933 (void) fclose(fp);
905 return -1;
906 }
907 else
908 {
909 mailerr("451 4.3.0", "temporary file write error");
910 (void) fclose(fp);
911 exit(ExitVal);
912 }
934 return -1;
913 }
914 return fd;
915}
916
917void
935 }
936 return fd;
937}
938
939void
918deliver(fd, name, bouncequota)
940deliver(fd, name)
919 int fd;
920 char *name;
941 int fd;
942 char *name;
921 bool bouncequota;
922{
923 struct stat fsb;
924 struct stat sb;
925 struct passwd *pw;
926 char path[MAXPATHLEN];
927 int mbfd = -1, nr = 0, nw, off;
928 char *p;
943{
944 struct stat fsb;
945 struct stat sb;
946 struct passwd *pw;
947 char path[MAXPATHLEN];
948 int mbfd = -1, nr = 0, nw, off;
949 char *p;
950 char *errcode;
929 off_t curoff;
930#ifdef CONTENTLENGTH
931 off_t headerbytes;
932 int readamount;
933#endif /* CONTENTLENGTH */
934 char biffmsg[100], buf[8*1024];
935 extern char *quad_to_string();
936
937
938 /*
939 ** Disallow delivery to unknown names -- special mailboxes can be
940 ** handled in the sendmail aliases file.
941 */
951 off_t curoff;
952#ifdef CONTENTLENGTH
953 off_t headerbytes;
954 int readamount;
955#endif /* CONTENTLENGTH */
956 char biffmsg[100], buf[8*1024];
957 extern char *quad_to_string();
958
959
960 /*
961 ** Disallow delivery to unknown names -- special mailboxes can be
962 ** handled in the sendmail aliases file.
963 */
964
942 if ((pw = getpwnam(name)) == NULL)
943 {
965 if ((pw = getpwnam(name)) == NULL)
966 {
944 if (ExitVal != EX_TEMPFAIL)
945 ExitVal = EX_UNAVAILABLE;
946 if (LMTPMode)
947 {
948 if (ExitVal == EX_TEMPFAIL)
949 printf("451 4.3.0 cannot lookup name: %s\r\n",
950 name);
951 else
952 printf("550 5.1.1 unknown name: %s\r\n", name);
953 }
967 if (ExitVal == EX_TEMPFAIL)
968 errcode = "451 4.3.0";
954 else
955 {
969 else
970 {
956 char *errcode = NULL;
957
958 if (ExitVal == EX_TEMPFAIL)
959 errcode = "451 4.3.0";
960 else
961 errcode = "550 5.1.1";
962 mailerr(errcode, "unknown name: %s", name);
971 ExitVal = EX_UNAVAILABLE;
972 errcode = "550 5.1.1";
963 }
973 }
974 mailerr(errcode, "Unknown name: %s", name);
964 return;
965 }
966 endpwent();
967
968 /*
969 ** Keep name reasonably short to avoid buffer overruns.
970 ** This isn't necessary on BSD because of the proper
971 ** definition of snprintf(), but it can cause problems

--- 43 unchanged lines hidden (view full) ---

1015#else /* MAILLOCK */
1016 p = path;
1017#endif /* MAILLOCK */
1018 if ((off = lockmbox(p)) != 0)
1019 {
1020 if (off == EX_TEMPFAIL || e_to_sys(off) == EX_TEMPFAIL)
1021 {
1022 ExitVal = EX_TEMPFAIL;
975 return;
976 }
977 endpwent();
978
979 /*
980 ** Keep name reasonably short to avoid buffer overruns.
981 ** This isn't necessary on BSD because of the proper
982 ** definition of snprintf(), but it can cause problems

--- 43 unchanged lines hidden (view full) ---

1026#else /* MAILLOCK */
1027 p = path;
1028#endif /* MAILLOCK */
1029 if ((off = lockmbox(p)) != 0)
1030 {
1031 if (off == EX_TEMPFAIL || e_to_sys(off) == EX_TEMPFAIL)
1032 {
1033 ExitVal = EX_TEMPFAIL;
1023 mailerr("451 4.3.0",
1024 "lockmailbox %s failed; error code %d %s",
1025 p, off, errno > 0 ? errstring(errno) : "");
1034 errcode = "451 4.3.0";
1026 }
1027 else
1035 }
1036 else
1028 {
1029 mailerr("551 5.3.0",
1030 "lockmailbox %s failed; error code %d %s",
1031 p, off, errno > 0 ? errstring(errno) : "");
1032 }
1037 errcode = "551 5.3.0";
1038
1039 mailerr(errcode, "lockmailbox %s failed; error code %d %s",
1040 p, off, errno > 0 ? errstring(errno) : "");
1033 return;
1034 }
1035
1036 if (lstat(path, &sb) < 0)
1037 {
1038 int save_errno;
1039 int mode = S_IRUSR|S_IWUSR;
1040 gid_t gid = U_GID;

--- 10 unchanged lines hidden (view full) ---

1051
1052 if (lstat(path, &sb) < 0)
1053 {
1054 ExitVal = EX_CANTCREAT;
1055 mailerr("550 5.2.0",
1056 "%s: lstat: file changed after open", path);
1057 goto err1;
1058 }
1041 return;
1042 }
1043
1044 if (lstat(path, &sb) < 0)
1045 {
1046 int save_errno;
1047 int mode = S_IRUSR|S_IWUSR;
1048 gid_t gid = U_GID;

--- 10 unchanged lines hidden (view full) ---

1059
1060 if (lstat(path, &sb) < 0)
1061 {
1062 ExitVal = EX_CANTCREAT;
1063 mailerr("550 5.2.0",
1064 "%s: lstat: file changed after open", path);
1065 goto err1;
1066 }
1059 if (mbfd == -1)
1067 if (mbfd < 0)
1060 {
1061 if (save_errno == EEXIST)
1062 goto tryagain;
1063
1064 /* open failed, don't try again */
1065 mailerr("450 4.2.0", "%s: %s", path,
1066 errstring(save_errno));
1067 goto err0;

--- 70 unchanged lines hidden (view full) ---

1138 {
1139 mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
1140 goto err1;
1141 }
1142
1143 if (!nobiff)
1144 {
1145 /* Get the starting offset of the new message for biff. */
1068 {
1069 if (save_errno == EEXIST)
1070 goto tryagain;
1071
1072 /* open failed, don't try again */
1073 mailerr("450 4.2.0", "%s: %s", path,
1074 errstring(save_errno));
1075 goto err0;

--- 70 unchanged lines hidden (view full) ---

1146 {
1147 mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
1148 goto err1;
1149 }
1150
1151 if (!nobiff)
1152 {
1153 /* Get the starting offset of the new message for biff. */
1146 curoff = lseek(mbfd, (off_t)0, SEEK_END);
1154 curoff = lseek(mbfd, (off_t) 0, SEEK_END);
1147 if (sizeof curoff > sizeof(long))
1148 (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n",
1149 name, quad_to_string(curoff));
1150 else
1151 (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n",
1152 name, (long) curoff);
1153 }
1154
1155 /* Copy the message into the file. */
1155 if (sizeof curoff > sizeof(long))
1156 (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n",
1157 name, quad_to_string(curoff));
1158 else
1159 (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n",
1160 name, (long) curoff);
1161 }
1162
1163 /* Copy the message into the file. */
1156 if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1)
1164 if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1)
1157 {
1165 {
1158 mailerr("450 4.2.0", "temporary file: %s",
1166 mailerr("450 4.2.0", "Temporary file: %s",
1159 errstring(errno));
1160 goto err1;
1161 }
1162#ifdef DEBUG
1163 fprintf(stderr, "before writing: euid = %d\n", geteuid());
1164#endif /* DEBUG */
1165#ifdef CONTENTLENGTH
1166 headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ;

--- 20 unchanged lines hidden (view full) ---

1187#else /* CONTENTLENGTH */
1188 while ((nr = read(fd, buf, sizeof(buf))) > 0)
1189 {
1190#endif /* CONTENTLENGTH */
1191 for (off = 0; off < nr; off += nw)
1192 {
1193 if ((nw = write(mbfd, buf + off, nr - off)) < 0)
1194 {
1167 errstring(errno));
1168 goto err1;
1169 }
1170#ifdef DEBUG
1171 fprintf(stderr, "before writing: euid = %d\n", geteuid());
1172#endif /* DEBUG */
1173#ifdef CONTENTLENGTH
1174 headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ;

--- 20 unchanged lines hidden (view full) ---

1195#else /* CONTENTLENGTH */
1196 while ((nr = read(fd, buf, sizeof(buf))) > 0)
1197 {
1198#endif /* CONTENTLENGTH */
1199 for (off = 0; off < nr; off += nw)
1200 {
1201 if ((nw = write(mbfd, buf + off, nr - off)) < 0)
1202 {
1203 errcode = "450 4.2.0";
1195#ifdef EDQUOT
1204#ifdef EDQUOT
1196 if (errno == EDQUOT && bouncequota)
1197 mailerr("552 5.2.2", "%s: %s",
1198 path, errstring(errno));
1199 else
1205 if (errno == EDQUOT && BounceQuota)
1206 errcode = "552 5.2.2";
1200#endif /* EDQUOT */
1207#endif /* EDQUOT */
1201 mailerr("450 4.2.0", "%s: %s",
1208 mailerr(errcode, "%s: %s",
1202 path, errstring(errno));
1203 goto err3;
1204 }
1205 }
1206 }
1207 if (nr < 0)
1208 {
1209 path, errstring(errno));
1210 goto err3;
1211 }
1212 }
1213 }
1214 if (nr < 0)
1215 {
1209 mailerr("450 4.2.0", "temporary file: %s",
1216 mailerr("450 4.2.0", "Temporary file: %s",
1210 errstring(errno));
1211 goto err3;
1212 }
1213
1214 /* Flush to disk, don't wait for update. */
1215 if (!nofsync && fsync(mbfd) < 0)
1216 {
1217 mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
1218err3:
1217 errstring(errno));
1218 goto err3;
1219 }
1220
1221 /* Flush to disk, don't wait for update. */
1222 if (!nofsync && fsync(mbfd) < 0)
1223 {
1224 mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
1225err3:
1219 if (setreuid(0, 0) < 0)
1220 {
1221#if 0
1222 /* already printed an error above for this recipient */
1223 (void) e_to_sys(errno);
1224 mailerr("450 4.2.0", "setreuid(0, 0): %s",
1225 errstring(errno));
1226#endif /* 0 */
1227 }
1226 (void) setreuid(0, 0);
1228#ifdef DEBUG
1229 fprintf(stderr, "reset euid = %d\n", geteuid());
1230#endif /* DEBUG */
1231 (void) ftruncate(mbfd, curoff);
1232err1: if (mbfd >= 0)
1233 (void) close(mbfd);
1234err0: unlockmbox();
1235 return;
1236 }
1237
1238 /* Close and check -- NFS doesn't write until the close. */
1239 if (close(mbfd))
1240 {
1227#ifdef DEBUG
1228 fprintf(stderr, "reset euid = %d\n", geteuid());
1229#endif /* DEBUG */
1230 (void) ftruncate(mbfd, curoff);
1231err1: if (mbfd >= 0)
1232 (void) close(mbfd);
1233err0: unlockmbox();
1234 return;
1235 }
1236
1237 /* Close and check -- NFS doesn't write until the close. */
1238 if (close(mbfd))
1239 {
1240 errcode = "450 4.2.0";
1241#ifdef EDQUOT
1241#ifdef EDQUOT
1242 if (errno == EDQUOT && bouncequota)
1243 mailerr("552 5.2.2", "%s: %s", path, errstring(errno));
1244 else
1242 if (errno == EDQUOT && BounceQuota)
1243 errcode = "552 5.2.2";
1245#endif /* EDQUOT */
1244#endif /* EDQUOT */
1246 mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
1245 mailerr(errcode, "%s: %s", path, errstring(errno));
1247 (void) truncate(path, curoff);
1248 }
1249 else if (!nobiff)
1250 notifybiff(biffmsg);
1251
1252 if (setreuid(0, 0) < 0)
1253 {
1254 mailerr("450 4.2.0", "setreuid(0, 0): %s",
1255 errstring(errno));
1256 goto err0;
1257 }
1258#ifdef DEBUG
1259 fprintf(stderr, "reset euid = %d\n", geteuid());
1260#endif /* DEBUG */
1261 unlockmbox();
1262 if (LMTPMode)
1246 (void) truncate(path, curoff);
1247 }
1248 else if (!nobiff)
1249 notifybiff(biffmsg);
1250
1251 if (setreuid(0, 0) < 0)
1252 {
1253 mailerr("450 4.2.0", "setreuid(0, 0): %s",
1254 errstring(errno));
1255 goto err0;
1256 }
1257#ifdef DEBUG
1258 fprintf(stderr, "reset euid = %d\n", geteuid());
1259#endif /* DEBUG */
1260 unlockmbox();
1261 if (LMTPMode)
1263 printf("250 2.1.5 %s OK\r\n", name);
1262 printf("250 2.1.5 %s Ok\r\n", name);
1264}
1265
1266/*
1267** user.lock files are necessary for compatibility with other
1268** systems, e.g., when the mail spool file is NFS exported.
1269** Alas, mailbox locking is more than just a local matter.
1270** EPA 11/94.
1271*/

--- 138 unchanged lines hidden (view full) ---

1410 /* No message, just return */
1411 if (msg == NULL)
1412 return;
1413
1414 /* Couldn't initialize addr struct */
1415 if (addr.sin_family == AF_UNSPEC)
1416 return;
1417
1263}
1264
1265/*
1266** user.lock files are necessary for compatibility with other
1267** systems, e.g., when the mail spool file is NFS exported.
1268** Alas, mailbox locking is more than just a local matter.
1269** EPA 11/94.
1270*/

--- 138 unchanged lines hidden (view full) ---

1409 /* No message, just return */
1410 if (msg == NULL)
1411 return;
1412
1413 /* Couldn't initialize addr struct */
1414 if (addr.sin_family == AF_UNSPEC)
1415 return;
1416
1418 if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1417 if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1419 return;
1420 len = strlen(msg) + 1;
1421 (void) sendto(f, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr));
1422}
1423
1424void
1425usage()
1426{

--- 7 unchanged lines hidden (view full) ---

1434mailerr(const char *hdr, const char *fmt, ...)
1435#else /* __STDC__ */
1436mailerr(hdr, fmt, va_alist)
1437 const char *hdr;
1438 const char *fmt;
1439 va_dcl
1440#endif /* __STDC__ */
1441{
1418 return;
1419 len = strlen(msg) + 1;
1420 (void) sendto(f, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr));
1421}
1422
1423void
1424usage()
1425{

--- 7 unchanged lines hidden (view full) ---

1433mailerr(const char *hdr, const char *fmt, ...)
1434#else /* __STDC__ */
1435mailerr(hdr, fmt, va_alist)
1436 const char *hdr;
1437 const char *fmt;
1438 va_dcl
1439#endif /* __STDC__ */
1440{
1441 size_t len = 0;
1442 va_list ap;
1443
1442 va_list ap;
1443
1444 (void) e_to_sys(errno);
1445
1444#ifdef __STDC__
1445 va_start(ap, fmt);
1446#else /* __STDC__ */
1447 va_start(ap);
1448#endif /* __STDC__ */
1446#ifdef __STDC__
1447 va_start(ap, fmt);
1448#else /* __STDC__ */
1449 va_start(ap);
1450#endif /* __STDC__ */
1451
1449 if (LMTPMode)
1450 {
1451 if (hdr != NULL)
1452 if (LMTPMode)
1453 {
1454 if (hdr != NULL)
1452 printf("%s ", hdr);
1453 (void) vprintf(fmt, ap);
1454 (void) printf("\r\n");
1455 {
1456 snprintf(ErrBuf, sizeof ErrBuf, "%s ", hdr);
1457 len = strlen(ErrBuf);
1458 }
1455 }
1459 }
1456 else
1457 {
1458 (void) e_to_sys(errno);
1459 vwarn(fmt, ap);
1460 }
1460 (void) vsnprintf(&ErrBuf[len], sizeof ErrBuf - len, fmt, ap);
1461
1462 if (!HoldErrs)
1463 flush_error();
1464
1465 /* Log the message to syslog. */
1466 if (!LMTPMode)
1467 syslog(LOG_ERR, "%s", ErrBuf);
1461}
1462
1463void
1468}
1469
1470void
1464vwarn(fmt, ap)
1465 const char *fmt;
1466 _BSD_VA_LIST_ ap;
1471flush_error()
1467{
1472{
1468 /*
1469 ** Log the message to stderr.
1470 **
1471 ** Don't use LOG_PERROR as an openlog() flag to do this,
1472 ** it's not portable enough.
1473 */
1474
1475 if (ExitVal != EX_USAGE)
1476 (void) fprintf(stderr, "mail.local: ");
1477 (void) vfprintf(stderr, fmt, ap);
1478 (void) fprintf(stderr, "\n");
1479
1480#if USE_VSYSLOG
1481 /* Log the message to syslog. */
1482 vsyslog(LOG_ERR, fmt, ap);
1483#else /* USE_VSYSLOG */
1473 if (LMTPMode)
1474 printf("%s\r\n", ErrBuf);
1475 else
1484 {
1476 {
1485 char fmtbuf[10240];
1486
1487 (void) vsnprintf(fmtbuf, sizeof fmtbuf, fmt, ap);
1488 syslog(LOG_ERR, "%s", fmtbuf);
1477 if (ExitVal != EX_USAGE)
1478 (void) fprintf(stderr, "mail.local: ");
1479 fprintf(stderr, "%s\n", ErrBuf);
1489 }
1480 }
1490#endif /* USE_VSYSLOG */
1491}
1492
1493/*
1494 * e_to_sys --
1495 * Guess which errno's are temporary. Gag me.
1496 */
1481}
1482
1483/*
1484 * e_to_sys --
1485 * Guess which errno's are temporary. Gag me.
1486 */
1487
1497int
1498e_to_sys(num)
1499 int num;
1500{
1501 /* Temporary failures override hard errors. */
1502 if (ExitVal == EX_TEMPFAIL)
1503 return ExitVal;
1504
1505 switch (num) /* Hopefully temporary errors. */
1506 {
1507#ifdef EDQUOT
1508 case EDQUOT: /* Disc quota exceeded */
1488int
1489e_to_sys(num)
1490 int num;
1491{
1492 /* Temporary failures override hard errors. */
1493 if (ExitVal == EX_TEMPFAIL)
1494 return ExitVal;
1495
1496 switch (num) /* Hopefully temporary errors. */
1497 {
1498#ifdef EDQUOT
1499 case EDQUOT: /* Disc quota exceeded */
1509 if (bouncequota)
1500 if (BounceQuota)
1510 {
1511 ExitVal = EX_UNAVAILABLE;
1512 break;
1513 }
1514 /* FALLTHROUGH */
1515#endif /* EDQUOT */
1516#ifdef EAGAIN
1517 case EAGAIN: /* Resource temporarily unavailable */

--- 124 unchanged lines hidden (view full) ---

1642mkstemp(path)
1643 char *path;
1644{
1645 int fd;
1646
1647 return (_gettemp(path, &fd) ? fd : -1);
1648}
1649
1501 {
1502 ExitVal = EX_UNAVAILABLE;
1503 break;
1504 }
1505 /* FALLTHROUGH */
1506#endif /* EDQUOT */
1507#ifdef EAGAIN
1508 case EAGAIN: /* Resource temporarily unavailable */

--- 124 unchanged lines hidden (view full) ---

1633mkstemp(path)
1634 char *path;
1635{
1636 int fd;
1637
1638 return (_gettemp(path, &fd) ? fd : -1);
1639}
1640
1650# if 0
1651char *
1652mktemp(path)
1653 char *path;
1654{
1655 return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
1656}
1657# endif /* 0 */
1658
1659static
1660_gettemp(path, doopen)
1661 char *path;
1662 register int *doopen;
1663{
1664 extern int errno;
1665 register char *start, *trv;
1666 struct stat sbuf;

--- 66 unchanged lines hidden ---
1641static
1642_gettemp(path, doopen)
1643 char *path;
1644 register int *doopen;
1645{
1646 extern int errno;
1647 register char *start, *trv;
1648 struct stat sbuf;

--- 66 unchanged lines hidden ---