1/* |
2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1990, 1993, 1994 4 * The Regents of the University of California. All rights reserved. 5 * 6 * By using this file, you agree to the terms and conditions set 7 * forth in the LICENSE file which can be found at the top level of 8 * the sendmail distribution. 9 * 10 */ 11 12#ifndef lint 13static char copyright[] = 14"@(#) Copyright (c) 1990, 1993, 1994\n\ 15 The Regents of the University of California. All rights reserved.\n"; 16#endif /* not lint */ 17 18#ifndef lint |
19static char sccsid[] = "@(#)mail.local.c 8.83 (Berkeley) 12/17/1998"; |
20#endif /* not lint */ 21 22/* 23 * This is not intended to work on System V derived systems 24 * such as Solaris or HP-UX, since they use a totally different 25 * approach to mailboxes (essentially, they have a setgid program 26 * rather than setuid, and they rely on the ability to "give away" 27 * files to do their work). IT IS NOT A BUG that this doesn't --- 69 unchanged lines hidden (view full) --- 97#if defined(ultrix) 98# define USE_VSYSLOG 0 99#endif 100 101#if defined(__osf__) 102# define USE_VSYSLOG 0 103#endif 104 |
105#if defined(NeXT) && !defined(__APPLE__) |
106# include <libc.h> 107# define _PATH_MAILDIR "/usr/spool/mail" 108# define __dead /* empty */ 109# define S_IRUSR S_IREAD 110# define S_IWUSR S_IWRITE 111#endif 112 113#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) --- 97 unchanged lines hidden (view full) --- 211#ifndef _PATH_MAILDIR 212# define _PATH_MAILDIR "/var/spool/mail" 213#endif 214 215#ifndef S_ISREG 216# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) 217#endif 218 |
219#ifndef MAILER_DAEMON 220# define MAILER_DAEMON "MAILER-DAEMON" 221#endif 222 |
223int eval = EX_OK; /* sysexits.h error value. */ 224int lmtpmode = 0; 225u_char tTdvect[100]; 226 227void deliver __P((int, char *, int, int)); 228void e_to_sys __P((int)); |
229void notifybiff __P((char *)); 230int store __P((char *, int)); 231void usage __P((void)); 232void vwarn __P((const char *, _BSD_VA_LIST_)); |
233void lockmbox __P((char *)); 234void unlockmbox __P((void)); 235void mailerr __P((const char *, const char *, ...)); 236void dolmtp __P((int, int)); 237 238int 239main(argc, argv) 240 int argc; --- 27 unchanged lines hidden (view full) --- 268 case 'b': 269 nobiff++; 270 break; 271 case 'd': /* Backward compatible. */ 272 break; 273 case 'f': 274 case 'r': /* Backward compatible. */ 275 if (from != NULL) { |
276 mailerr(NULL, "multiple -f options"); |
277 usage(); 278 } 279 from = optarg; 280 break; 281 case 'l': 282 lmtpmode++; 283 break; 284 case 's': --- 56 unchanged lines hidden (view full) --- 341 while (isascii(*p) && 342 (isalnum(*p) || *p == '.' || 343 *p == '-' || *p == ':')) 344 p++; 345 if (*p++ != ']') 346 return NULL; 347 } else { 348 while ((isascii(*p) && isalnum(*p)) || |
349 strchr(".-_", *p)) |
350 p++; 351 } 352 if (*p == ',' && p[1] == '@') 353 p++; 354 else if (*p == ':' && p[1] != '@') 355 p++; 356 else 357 return NULL; 358 } 359 |
360 s = p; 361 |
362 /* local-part */ 363 if (*p == '\"') { 364 p++; 365 while (*p && *p != '\"') { 366 if (*p == '\\') { 367 if (!*++p) 368 return NULL; 369 } --- 23 unchanged lines hidden (view full) --- 393 while (isascii(*p) && 394 (isalnum(*p) || *p == '.' || 395 *p == '-' || *p == ':')) 396 p++; 397 if (*p++ != ']') 398 return NULL; 399 } else { 400 while ((isascii(*p) && isalnum(*p)) || |
401 strchr(".-_", *p)) |
402 p++; 403 } 404 } 405 406 if (*p++ != '>') 407 return NULL; 408 if (*p && *p != ' ') 409 return NULL; 410 len = p - s - 1; |
411 if (*s == '\0' || len <= 0) 412 { 413 s = MAILER_DAEMON; 414 len = strlen(s); 415 } |
416 417 p = malloc(len + 1); 418 if (p == NULL) { 419 printf("421 4.3.0 memory exhausted\r\n"); 420 exit(EX_TEMPFAIL); 421 } 422 423 strncpy(p, s, len); --- 171 unchanged lines hidden (view full) --- 595 } 596} 597 598int 599store(from, lmtprcpts) 600 char *from; 601 int lmtprcpts; 602{ |
603 FILE *fp = NULL; |
604 time_t tval; 605 int fd, eline; 606 char line[2048]; 607 char tmpbuf[sizeof _PATH_LOCTMP + 1]; 608 609 strcpy(tmpbuf, _PATH_LOCTMP); 610 if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) { 611 if (lmtprcpts) { 612 printf("451 4.3.0 unable to open temporary file\r\n"); 613 return -1; 614 } else { |
615 mailerr("451 4.3.0", "unable to open temporary file"); 616 exit(eval); |
617 } 618 } 619 (void)unlink(tmpbuf); 620 621 if (lmtpmode) { 622 printf("354 go ahead\r\n"); 623 fflush(stdout); 624 } 625 626 (void)time(&tval); 627 (void)fprintf(fp, "From %s %s", from, ctime(&tval)); 628 629 line[0] = '\0'; 630 for (eline = 1; fgets(line, sizeof(line), stdin);) { |
631 size_t line_len = strlen(line); 632 633 if (line_len >= 2 && 634 line[line_len - 2] == '\r' && 635 line[line_len - 1] == '\n') { 636 strcpy(line + line_len - 2, "\n"); |
637 } 638 if (lmtprcpts && line[0] == '.') { |
639 char *src = line + 1, *dest = line; 640 |
641 if (line[1] == '\n') 642 goto lmtpdot; |
643 while (*src != '\0') 644 *dest++ = *src++; 645 *dest = '\0'; |
646 } 647 if (line[0] == '\n') 648 eline = 1; 649 else { 650 if (eline && line[0] == 'F' && 651 !memcmp(line, "From ", 5)) 652 (void)putc('>', fp); 653 eline = 0; 654 } 655 (void)fprintf(fp, "%s", line); 656 if (ferror(fp)) { 657 if (lmtprcpts) { 658 while (lmtprcpts--) { 659 printf("451 4.3.0 temporary file write error\r\n"); 660 } 661 fclose(fp); 662 return -1; 663 } else { |
664 mailerr("451 4.3.0", 665 "temporary file write error"); 666 fclose(fp); 667 exit(eval); |
668 } 669 } 670 } 671 672 if (lmtprcpts) { 673 /* Got a premature EOF -- toss message and exit */ 674 exit(EX_OK); 675 } --- 10 unchanged lines hidden (view full) --- 686 if (fflush(fp) == EOF || ferror(fp)) { 687 if (lmtprcpts) { 688 while (lmtprcpts--) { 689 printf("451 4.3.0 temporary file write error\r\n"); 690 } 691 fclose(fp); 692 return -1; 693 } else { |
694 mailerr("451 4.3.0", "temporary file write error"); 695 fclose(fp); 696 exit(eval); |
697 } 698 } 699 return (fd); 700} 701 702void 703deliver(fd, name, nobiff, nofsync) 704 int fd; --- 18 unchanged lines hidden (view full) --- 723 if (lmtpmode) { 724 if (eval == EX_TEMPFAIL) { 725 printf("451 4.3.0 cannot lookup name: %s\r\n", name); 726 } else { 727 printf("550 5.1.1 unknown name: %s\r\n", name); 728 } 729 } 730 else { |
731 char *errcode = NULL; 732 733 if (eval == EX_TEMPFAIL) 734 errcode = "451 4.3.0"; 735 else 736 errcode = "550 5.1.1"; 737 mailerr(errcode, "unknown name: %s", name); |
738 } 739 return; 740 } 741 endpwent(); 742 743 /* 744 * Keep name reasonably short to avoid buffer overruns. 745 * This isn't necessary on BSD because of the proper --- 38 unchanged lines hidden (view full) --- 784tryagain: 785 lockmbox(path); 786 if (lstat(path, &sb) < 0) { 787 mbfd = open(path, 788 O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); 789 if (lstat(path, &sb) < 0) 790 { 791 eval = EX_CANTCREAT; |
792 mailerr("550 5.2.0", 793 "%s: lstat: file changed after open", path); |
794 goto err1; 795 } 796 else 797 sb.st_uid = pw->pw_uid; 798 if (mbfd == -1) { 799 if (errno == EEXIST) 800 goto tryagain; 801 } else if (fchown(mbfd, pw->pw_uid, pw->pw_gid)) { --- 22 unchanged lines hidden (view full) --- 824 !S_ISREG(fsb.st_mode) || 825 sb.st_dev != fsb.st_dev || 826 sb.st_ino != fsb.st_ino || 827#if HAS_ST_GEN && 0 /* AFS returns random values for st_gen */ 828 sb.st_gen != fsb.st_gen || 829#endif 830 sb.st_uid != fsb.st_uid) { 831 eval = EX_TEMPFAIL; |
832 mailerr("550 5.2.0", "%s: fstat: file changed after open", 833 path); |
834 goto err1; 835 } 836 837 /* Wait until we can get a lock on the file. */ 838 if (flock(mbfd, LOCK_EX)) { 839 mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); 840 goto err1; 841 } --- 36 unchanged lines hidden (view full) --- 878 goto err3; 879 } 880 881 /* Flush to disk, don't wait for update. */ 882 if (!nofsync && fsync(mbfd)) { 883 mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); 884err3: 885 if (setreuid(0, 0) < 0) { |
886#if 0 887 /* already printed an error above for this recipient */ |
888 e_to_sys(errno); 889 mailerr("450 4.2.0", "setreuid(0, 0): %s", 890 strerror(errno)); |
891#endif |
892 } 893#ifdef DEBUG 894 printf("reset euid = %d\n", geteuid()); 895#endif 896 (void)ftruncate(mbfd, curoff); 897err1: (void)close(mbfd); 898err0: unlockmbox(); 899 return; --- 86 unchanged lines hidden (view full) --- 986 struct servent *sp; 987 int len; 988 989 if (addr.sin_family == 0) { 990 /* Be silent if biff service not available. */ 991 if ((sp = getservbyname("biff", "udp")) == NULL) 992 return; 993 if ((hp = gethostbyname("localhost")) == NULL) { |
994 return; 995 } 996 addr.sin_family = hp->h_addrtype; 997 memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); 998 addr.sin_port = sp->s_port; 999 } 1000 if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { |
1001 return; 1002 } 1003 len = strlen(msg) + 1; |
1004 (void) sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)); |
1005} 1006 1007void 1008usage() 1009{ 1010 eval = EX_USAGE; |
1011 mailerr(NULL, "usage: mail.local [-b] [-l] [-f from] [-s] user ..."); 1012 exit(eval); |
1013} 1014 1015void 1016#ifdef __STDC__ 1017mailerr(const char *hdr, const char *fmt, ...) 1018#else 1019mailerr(hdr, fmt, va_alist) 1020 const char *hdr; --- 5 unchanged lines hidden (view full) --- 1026 1027#ifdef __STDC__ 1028 va_start(ap, fmt); 1029#else 1030 va_start(ap); 1031#endif 1032 if (lmtpmode) 1033 { |
1034 if (hdr != NULL) 1035 printf("%s ", hdr); |
1036 vprintf(fmt, ap); 1037 printf("\r\n"); 1038 } 1039 else 1040 { 1041 e_to_sys(errno); 1042 vwarn(fmt, ap); 1043 } 1044} 1045 |
1046void |
1047vwarn(fmt, ap) 1048 const char *fmt; 1049 _BSD_VA_LIST_ ap; 1050{ 1051 /* 1052 * Log the message to stderr. 1053 * 1054 * Don't use LOG_PERROR as an openlog() flag to do this, --- 263 unchanged lines hidden --- |