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 --- |