1c2aa98e2SPeter Wemm /* 23299c2f1SGregory Neil Shapiro * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. 33299c2f1SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 5c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 6c2aa98e2SPeter Wemm * 7c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 8c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 9c2aa98e2SPeter Wemm * the sendmail distribution. 10c2aa98e2SPeter Wemm * 11c2aa98e2SPeter Wemm */ 12c2aa98e2SPeter Wemm 13c2aa98e2SPeter Wemm #ifndef lint 14c2aa98e2SPeter Wemm static char copyright[] = 153299c2f1SGregory Neil Shapiro "@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ 163299c2f1SGregory Neil Shapiro All rights reserved.\n\ 173299c2f1SGregory Neil Shapiro Copyright (c) 1988, 1993\n\ 18c2aa98e2SPeter Wemm The Regents of the University of California. All rights reserved.\n"; 193299c2f1SGregory Neil Shapiro #endif /* ! lint */ 20c2aa98e2SPeter Wemm 21c2aa98e2SPeter Wemm #ifndef lint 22d995d2baSGregory Neil Shapiro static char id[] = "@(#)$Id: rmail.c,v 8.39.4.8 2000/09/16 22:20:25 gshapiro Exp $"; 233299c2f1SGregory Neil Shapiro #endif /* ! lint */ 243299c2f1SGregory Neil Shapiro 253299c2f1SGregory Neil Shapiro /* $FreeBSD$ */ 26c2aa98e2SPeter Wemm 27c2aa98e2SPeter Wemm /* 28c2aa98e2SPeter Wemm * RMAIL -- UUCP mail server. 29c2aa98e2SPeter Wemm * 30c2aa98e2SPeter Wemm * This program reads the >From ... remote from ... lines that UUCP is so 31c2aa98e2SPeter Wemm * fond of and turns them into something reasonable. It then execs sendmail 32c2aa98e2SPeter Wemm * with various options built from these lines. 33c2aa98e2SPeter Wemm * 34c2aa98e2SPeter Wemm * The expected syntax is: 35c2aa98e2SPeter Wemm * 36c2aa98e2SPeter Wemm * <user> := [-a-z0-9]+ 37c2aa98e2SPeter Wemm * <date> := ctime format 38c2aa98e2SPeter Wemm * <site> := [-a-z0-9!]+ 39c2aa98e2SPeter Wemm * <blank line> := "^\n$" 40c2aa98e2SPeter Wemm * <from> := "From" <space> <user> <space> <date> 41c2aa98e2SPeter Wemm * [<space> "remote from" <space> <site>] 42c2aa98e2SPeter Wemm * <forward> := ">" <from> 43c2aa98e2SPeter Wemm * msg := <from> <forward>* <blank-line> <body> 44c2aa98e2SPeter Wemm * 45c2aa98e2SPeter Wemm * The output of rmail(8) compresses the <forward> lines into a single 46c2aa98e2SPeter Wemm * from path. 47c2aa98e2SPeter Wemm * 48c2aa98e2SPeter Wemm * The err(3) routine is included here deliberately to make this code 49c2aa98e2SPeter Wemm * a bit more portable. 50c2aa98e2SPeter Wemm */ 513299c2f1SGregory Neil Shapiro 523299c2f1SGregory Neil Shapiro #include <sys/types.h> 53c2aa98e2SPeter Wemm #include <sys/param.h> 54c2aa98e2SPeter Wemm #include <sys/stat.h> 55c2aa98e2SPeter Wemm #include <sys/wait.h> 56c2aa98e2SPeter Wemm 57c2aa98e2SPeter Wemm #include <ctype.h> 58c2aa98e2SPeter Wemm #include <fcntl.h> 59c2aa98e2SPeter Wemm #ifdef BSD4_4 60c2aa98e2SPeter Wemm # define FORK vfork 61c2aa98e2SPeter Wemm # include <paths.h> 623299c2f1SGregory Neil Shapiro #else /* BSD4_4 */ 63c2aa98e2SPeter Wemm # define FORK fork 64c2aa98e2SPeter Wemm # ifndef _PATH_SENDMAIL 65c2aa98e2SPeter Wemm # define _PATH_SENDMAIL "/usr/lib/sendmail" 663299c2f1SGregory Neil Shapiro # endif /* ! _PATH_SENDMAIL */ 673299c2f1SGregory Neil Shapiro #endif /* BSD4_4 */ 68c2aa98e2SPeter Wemm #include <stdio.h> 69c2aa98e2SPeter Wemm #include <stdlib.h> 70c2aa98e2SPeter Wemm #include <string.h> 71c2aa98e2SPeter Wemm #include <unistd.h> 72c2aa98e2SPeter Wemm #ifdef EX_OK 73c2aa98e2SPeter Wemm # undef EX_OK /* unistd.h may have another use for this */ 743299c2f1SGregory Neil Shapiro #endif /* EX_OK */ 75c2aa98e2SPeter Wemm #include <sysexits.h> 76c2aa98e2SPeter Wemm 77c2aa98e2SPeter Wemm #ifndef MAX 78c2aa98e2SPeter Wemm # define MAX(a, b) ((a) < (b) ? (b) : (a)) 793299c2f1SGregory Neil Shapiro #endif /* ! MAX */ 80c2aa98e2SPeter Wemm 81c2aa98e2SPeter Wemm #ifndef __P 82c2aa98e2SPeter Wemm # ifdef __STDC__ 83c2aa98e2SPeter Wemm # define __P(protos) protos 843299c2f1SGregory Neil Shapiro # else /* __STDC__ */ 85c2aa98e2SPeter Wemm # define __P(protos) () 86c2aa98e2SPeter Wemm # define const 873299c2f1SGregory Neil Shapiro # endif /* __STDC__ */ 883299c2f1SGregory Neil Shapiro #endif /* ! __P */ 89c2aa98e2SPeter Wemm 903299c2f1SGregory Neil Shapiro #ifndef STDIN_FILENO 913299c2f1SGregory Neil Shapiro # define STDIN_FILENO 0 923299c2f1SGregory Neil Shapiro #endif /* ! STDIN_FILENO */ 933299c2f1SGregory Neil Shapiro 94d995d2baSGregory Neil Shapiro #if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300 || defined(HPUX11) 95c2aa98e2SPeter Wemm # define HASSNPRINTF 1 96d995d2baSGregory Neil Shapiro #endif /* defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300 || defined(HPUX11) */ 97c2aa98e2SPeter Wemm 98c2aa98e2SPeter Wemm #if defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) 99c2aa98e2SPeter Wemm # define memmove(d, s, l) (bcopy((s), (d), (l))) 1003299c2f1SGregory Neil Shapiro #endif /* defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) */ 101c2aa98e2SPeter Wemm 102c2aa98e2SPeter Wemm #if !HASSNPRINTF 103c2aa98e2SPeter Wemm extern int snprintf __P((char *, size_t, const char *, ...)); 104c2aa98e2SPeter Wemm #endif /* !HASSNPRINTF */ 105c2aa98e2SPeter Wemm 1063299c2f1SGregory Neil Shapiro #if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) 1073299c2f1SGregory Neil Shapiro # ifndef HASSTRERROR 1083299c2f1SGregory Neil Shapiro # define HASSTRERROR 1 1093299c2f1SGregory Neil Shapiro # endif /* ! HASSTRERROR */ 1103299c2f1SGregory Neil Shapiro #endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || 1113299c2f1SGregory Neil Shapiro defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ 112c2aa98e2SPeter Wemm 1133299c2f1SGregory Neil Shapiro #if defined(SUNOS403) || defined(NeXT) || (defined(MACH) && defined(i386) && !defined(__GNU__)) || defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) || defined(ALTOS_SYSTEM_V) || defined(RISCOS) || defined(_AUX_SOURCE) || defined(UMAXV) || defined(titan) || defined(UNIXWARE) || defined(sony_news) || defined(luna) || defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(__MAXION__) 1143299c2f1SGregory Neil Shapiro # undef WIFEXITED 1153299c2f1SGregory Neil Shapiro # undef WEXITSTATUS 1163299c2f1SGregory Neil Shapiro # define WIFEXITED(st) (((st) & 0377) == 0) 1173299c2f1SGregory Neil Shapiro # define WEXITSTATUS(st) (((st) >> 8) & 0377) 1183299c2f1SGregory Neil Shapiro #endif /* defined(SUNOS403) || defined(NeXT) || (defined(MACH) && defined(i386) && !defined(__GNU__)) || defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) || defined(ALTOS_SYSTEM_V) || defined(RISCOS) || defined(_AUX_SOURCE) || defined(UMAXV) || defined(titan) || defined(UNIXWARE) || defined(sony_news) || defined(luna) || defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(__MAXION__) */ 1193299c2f1SGregory Neil Shapiro 1203299c2f1SGregory Neil Shapiro 1213299c2f1SGregory Neil Shapiro #include "sendmail/errstring.h" 1223299c2f1SGregory Neil Shapiro 1233299c2f1SGregory Neil Shapiro static void err __P((int, const char *, ...)); 1243299c2f1SGregory Neil Shapiro static void usage __P((void)); 1253299c2f1SGregory Neil Shapiro static char *xalloc __P((int)); 126c2aa98e2SPeter Wemm 127c2aa98e2SPeter Wemm #define newstr(s) strcpy(xalloc(strlen(s) + 1), s) 128c2aa98e2SPeter Wemm 1293299c2f1SGregory Neil Shapiro static char * 130c2aa98e2SPeter Wemm xalloc(sz) 131c2aa98e2SPeter Wemm register int sz; 132c2aa98e2SPeter Wemm { 133c2aa98e2SPeter Wemm register char *p; 134c2aa98e2SPeter Wemm 135c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 136c2aa98e2SPeter Wemm if (sz <= 0) 137c2aa98e2SPeter Wemm sz = 1; 138c2aa98e2SPeter Wemm 139c2aa98e2SPeter Wemm p = malloc((unsigned) sz); 140c2aa98e2SPeter Wemm if (p == NULL) 141c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "out of memory"); 142c2aa98e2SPeter Wemm return (p); 143c2aa98e2SPeter Wemm } 144c2aa98e2SPeter Wemm 145c2aa98e2SPeter Wemm int 146c2aa98e2SPeter Wemm main(argc, argv) 147c2aa98e2SPeter Wemm int argc; 148c2aa98e2SPeter Wemm char *argv[]; 149c2aa98e2SPeter Wemm { 1503299c2f1SGregory Neil Shapiro int ch, debug, i, pdes[2], pid, status; 15176b7bf71SPeter Wemm size_t fplen = 0, fptlen = 0, len; 152c2aa98e2SPeter Wemm off_t offset; 1533299c2f1SGregory Neil Shapiro FILE *fp; 15476b7bf71SPeter Wemm char *addrp = NULL, *domain, *p, *t; 155c2aa98e2SPeter Wemm char *from_path, *from_sys, *from_user; 156d995d2baSGregory Neil Shapiro char **args, buf[2048], lbuf[2048]; 1573299c2f1SGregory Neil Shapiro struct stat sb; 1583299c2f1SGregory Neil Shapiro extern char *optarg; 1593299c2f1SGregory Neil Shapiro extern int optind; 160c2aa98e2SPeter Wemm 161c2aa98e2SPeter Wemm debug = 0; 162c2aa98e2SPeter Wemm domain = "UUCP"; /* Default "domain". */ 163b2ee1660SPeter Wemm while ((ch = getopt(argc, argv, "D:T")) != -1) 1643299c2f1SGregory Neil Shapiro { 1653299c2f1SGregory Neil Shapiro switch (ch) 1663299c2f1SGregory Neil Shapiro { 167c2aa98e2SPeter Wemm case 'T': 168c2aa98e2SPeter Wemm debug = 1; 169c2aa98e2SPeter Wemm break; 1703299c2f1SGregory Neil Shapiro 171c2aa98e2SPeter Wemm case 'D': 172c2aa98e2SPeter Wemm domain = optarg; 173c2aa98e2SPeter Wemm break; 1743299c2f1SGregory Neil Shapiro 175c2aa98e2SPeter Wemm case '?': 176c2aa98e2SPeter Wemm default: 177c2aa98e2SPeter Wemm usage(); 178c2aa98e2SPeter Wemm } 1793299c2f1SGregory Neil Shapiro } 1803299c2f1SGregory Neil Shapiro 181c2aa98e2SPeter Wemm argc -= optind; 182c2aa98e2SPeter Wemm argv += optind; 183c2aa98e2SPeter Wemm 184c2aa98e2SPeter Wemm if (argc < 1) 185c2aa98e2SPeter Wemm usage(); 186c2aa98e2SPeter Wemm 187c2aa98e2SPeter Wemm from_path = from_sys = from_user = NULL; 1883299c2f1SGregory Neil Shapiro for (offset = 0; ; ) 1893299c2f1SGregory Neil Shapiro { 190c2aa98e2SPeter Wemm /* Get and nul-terminate the line. */ 191c2aa98e2SPeter Wemm if (fgets(lbuf, sizeof(lbuf), stdin) == NULL) 192c2aa98e2SPeter Wemm exit(EX_DATAERR); 193c2aa98e2SPeter Wemm if ((p = strchr(lbuf, '\n')) == NULL) 194c2aa98e2SPeter Wemm err(EX_DATAERR, "line too long"); 195c2aa98e2SPeter Wemm *p = '\0'; 196c2aa98e2SPeter Wemm 197c2aa98e2SPeter Wemm /* Parse lines until reach a non-"From" line. */ 198c2aa98e2SPeter Wemm if (!strncmp(lbuf, "From ", 5)) 199c2aa98e2SPeter Wemm addrp = lbuf + 5; 200c2aa98e2SPeter Wemm else if (!strncmp(lbuf, ">From ", 6)) 201c2aa98e2SPeter Wemm addrp = lbuf + 6; 202c2aa98e2SPeter Wemm else if (offset == 0) 203c2aa98e2SPeter Wemm err(EX_DATAERR, 204c2aa98e2SPeter Wemm "missing or empty From line: %s", lbuf); 2053299c2f1SGregory Neil Shapiro else 2063299c2f1SGregory Neil Shapiro { 207c2aa98e2SPeter Wemm *p = '\n'; 208c2aa98e2SPeter Wemm break; 209c2aa98e2SPeter Wemm } 210c2aa98e2SPeter Wemm 2113299c2f1SGregory Neil Shapiro if (addrp == NULL || *addrp == '\0') 212c2aa98e2SPeter Wemm err(EX_DATAERR, "corrupted From line: %s", lbuf); 213c2aa98e2SPeter Wemm 214c2aa98e2SPeter Wemm /* Use the "remote from" if it exists. */ 215c2aa98e2SPeter Wemm for (p = addrp; (p = strchr(p + 1, 'r')) != NULL; ) 2163299c2f1SGregory Neil Shapiro { 2173299c2f1SGregory Neil Shapiro if (!strncmp(p, "remote from ", 12)) 2183299c2f1SGregory Neil Shapiro { 2193299c2f1SGregory Neil Shapiro for (t = p += 12; *t != '\0'; ++t) 2203299c2f1SGregory Neil Shapiro { 2213299c2f1SGregory Neil Shapiro if (isascii(*t) && isspace(*t)) 2223299c2f1SGregory Neil Shapiro break; 2233299c2f1SGregory Neil Shapiro } 224c2aa98e2SPeter Wemm *t = '\0'; 225c2aa98e2SPeter Wemm if (debug) 2263299c2f1SGregory Neil Shapiro fprintf(stderr, "remote from: %s\n", p); 227c2aa98e2SPeter Wemm break; 228c2aa98e2SPeter Wemm } 2293299c2f1SGregory Neil Shapiro } 230c2aa98e2SPeter Wemm 231c2aa98e2SPeter Wemm /* Else use the string up to the last bang. */ 2323299c2f1SGregory Neil Shapiro if (p == NULL) 2333299c2f1SGregory Neil Shapiro { 234c2aa98e2SPeter Wemm if (*addrp == '!') 2353299c2f1SGregory Neil Shapiro err(EX_DATAERR, "bang starts address: %s", 2363299c2f1SGregory Neil Shapiro addrp); 2373299c2f1SGregory Neil Shapiro else if ((t = strrchr(addrp, '!')) != NULL) 2383299c2f1SGregory Neil Shapiro { 239c2aa98e2SPeter Wemm *t = '\0'; 240c2aa98e2SPeter Wemm p = addrp; 241c2aa98e2SPeter Wemm addrp = t + 1; 242c2aa98e2SPeter Wemm if (*addrp == '\0') 243c2aa98e2SPeter Wemm err(EX_DATAERR, 244c2aa98e2SPeter Wemm "corrupted From line: %s", lbuf); 245c2aa98e2SPeter Wemm if (debug) 2463299c2f1SGregory Neil Shapiro fprintf(stderr, "bang: %s\n", p); 247c2aa98e2SPeter Wemm } 248c2aa98e2SPeter Wemm } 2493299c2f1SGregory Neil Shapiro 250c2aa98e2SPeter Wemm /* 'p' now points to any system string from this line. */ 2513299c2f1SGregory Neil Shapiro if (p != NULL) 2523299c2f1SGregory Neil Shapiro { 253c2aa98e2SPeter Wemm /* Nul terminate it as necessary. */ 2543299c2f1SGregory Neil Shapiro for (t = p; *t != '\0'; ++t) 2553299c2f1SGregory Neil Shapiro { 2563299c2f1SGregory Neil Shapiro if (isascii(*t) && isspace(*t)) 2573299c2f1SGregory Neil Shapiro break; 2583299c2f1SGregory Neil Shapiro } 259c2aa98e2SPeter Wemm *t = '\0'; 260c2aa98e2SPeter Wemm 261c2aa98e2SPeter Wemm /* If the first system, copy to the from_sys string. */ 2623299c2f1SGregory Neil Shapiro if (from_sys == NULL) 2633299c2f1SGregory Neil Shapiro { 264c2aa98e2SPeter Wemm from_sys = newstr(p); 265c2aa98e2SPeter Wemm if (debug) 2663299c2f1SGregory Neil Shapiro fprintf(stderr, "from_sys: %s\n", 2673299c2f1SGregory Neil Shapiro from_sys); 268c2aa98e2SPeter Wemm } 269c2aa98e2SPeter Wemm 270c2aa98e2SPeter Wemm /* Concatenate to the path string. */ 271c2aa98e2SPeter Wemm len = t - p; 2723299c2f1SGregory Neil Shapiro if (from_path == NULL) 2733299c2f1SGregory Neil Shapiro { 274c2aa98e2SPeter Wemm fplen = 0; 275c2aa98e2SPeter Wemm if ((from_path = malloc(fptlen = 256)) == NULL) 276c2aa98e2SPeter Wemm err(EX_TEMPFAIL, NULL); 277c2aa98e2SPeter Wemm } 2783299c2f1SGregory Neil Shapiro if (fplen + len + 2 > fptlen) 2793299c2f1SGregory Neil Shapiro { 280c2aa98e2SPeter Wemm fptlen += MAX(fplen + len + 2, 256); 2813299c2f1SGregory Neil Shapiro if ((from_path = realloc(from_path, 2823299c2f1SGregory Neil Shapiro fptlen)) == NULL) 283c2aa98e2SPeter Wemm err(EX_TEMPFAIL, NULL); 284c2aa98e2SPeter Wemm } 285c2aa98e2SPeter Wemm memmove(from_path + fplen, p, len); 286c2aa98e2SPeter Wemm fplen += len; 287c2aa98e2SPeter Wemm from_path[fplen++] = '!'; 288c2aa98e2SPeter Wemm from_path[fplen] = '\0'; 289c2aa98e2SPeter Wemm } 290c2aa98e2SPeter Wemm 291c2aa98e2SPeter Wemm /* Save off from user's address; the last one wins. */ 2923299c2f1SGregory Neil Shapiro for (p = addrp; *p != '\0'; ++p) 2933299c2f1SGregory Neil Shapiro { 2943299c2f1SGregory Neil Shapiro if (isascii(*p) && isspace(*p)) 2953299c2f1SGregory Neil Shapiro break; 2963299c2f1SGregory Neil Shapiro } 297c2aa98e2SPeter Wemm *p = '\0'; 298c2aa98e2SPeter Wemm if (*addrp == '\0') 299c2aa98e2SPeter Wemm addrp = "<>"; 300c2aa98e2SPeter Wemm if (from_user != NULL) 301c2aa98e2SPeter Wemm free(from_user); 302c2aa98e2SPeter Wemm from_user = newstr(addrp); 303c2aa98e2SPeter Wemm 3043299c2f1SGregory Neil Shapiro if (debug) 3053299c2f1SGregory Neil Shapiro { 306c2aa98e2SPeter Wemm if (from_path != NULL) 3073299c2f1SGregory Neil Shapiro fprintf(stderr, "from_path: %s\n", from_path); 3083299c2f1SGregory Neil Shapiro fprintf(stderr, "from_user: %s\n", from_user); 309c2aa98e2SPeter Wemm } 310c2aa98e2SPeter Wemm 311c2aa98e2SPeter Wemm if (offset != -1) 312c2aa98e2SPeter Wemm offset = (off_t)ftell(stdin); 313c2aa98e2SPeter Wemm } 314c2aa98e2SPeter Wemm 315d995d2baSGregory Neil Shapiro 316d995d2baSGregory Neil Shapiro /* Allocate args (with room for sendmail args as well as recipients */ 317d995d2baSGregory Neil Shapiro args = (char **)xalloc(sizeof(*args) * (10 + argc)); 318d995d2baSGregory Neil Shapiro 319c2aa98e2SPeter Wemm i = 0; 320c2aa98e2SPeter Wemm args[i++] = _PATH_SENDMAIL; /* Build sendmail's argument list. */ 321d995d2baSGregory Neil Shapiro args[i++] = "-G"; /* relay submission */ 322c2aa98e2SPeter Wemm args[i++] = "-oee"; /* No errors, just status. */ 323829be59cSPeter Wemm #ifdef QUEUE_ONLY 324c2aa98e2SPeter Wemm args[i++] = "-odq"; /* Queue it, don't try to deliver. */ 325829be59cSPeter Wemm #else 326829be59cSPeter Wemm args[i++] = "-odi"; /* Deliver in foreground. */ 327829be59cSPeter Wemm #endif 328c2aa98e2SPeter Wemm args[i++] = "-oi"; /* Ignore '.' on a line by itself. */ 329c2aa98e2SPeter Wemm 330c2aa98e2SPeter Wemm /* set from system and protocol used */ 331c2aa98e2SPeter Wemm if (from_sys == NULL) 3323299c2f1SGregory Neil Shapiro snprintf(buf, sizeof(buf), "-p%s", domain); 333c2aa98e2SPeter Wemm else if (strchr(from_sys, '.') == NULL) 3343299c2f1SGregory Neil Shapiro snprintf(buf, sizeof(buf), "-p%s:%s.%s", 335c2aa98e2SPeter Wemm domain, from_sys, domain); 336c2aa98e2SPeter Wemm else 3373299c2f1SGregory Neil Shapiro snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys); 338c2aa98e2SPeter Wemm args[i++] = newstr(buf); 339c2aa98e2SPeter Wemm 340c2aa98e2SPeter Wemm /* Set name of ``from'' person. */ 3413299c2f1SGregory Neil Shapiro snprintf(buf, sizeof(buf), "-f%s%s", 342c2aa98e2SPeter Wemm from_path ? from_path : "", from_user); 343c2aa98e2SPeter Wemm args[i++] = newstr(buf); 344c2aa98e2SPeter Wemm 345c2aa98e2SPeter Wemm /* 3463299c2f1SGregory Neil Shapiro ** Don't copy arguments beginning with - as they will be 3473299c2f1SGregory Neil Shapiro ** passed to sendmail and could be interpreted as flags. 3483299c2f1SGregory Neil Shapiro ** To prevent confusion of sendmail wrap < and > around 3493299c2f1SGregory Neil Shapiro ** the address (helps to pass addrs like @gw1,@gw2:aa@bb) 350c2aa98e2SPeter Wemm */ 3513299c2f1SGregory Neil Shapiro 352d995d2baSGregory Neil Shapiro while (*argv != NULL) 3533299c2f1SGregory Neil Shapiro { 354c2aa98e2SPeter Wemm if (**argv == '-') 355c2aa98e2SPeter Wemm err(EX_USAGE, "dash precedes argument: %s", *argv); 3563299c2f1SGregory Neil Shapiro 357c2aa98e2SPeter Wemm if (strchr(*argv, ',') == NULL || strchr(*argv, '<') != NULL) 358c2aa98e2SPeter Wemm args[i++] = *argv; 3593299c2f1SGregory Neil Shapiro else 3603299c2f1SGregory Neil Shapiro { 3613299c2f1SGregory Neil Shapiro len = strlen(*argv) + 3; 3623299c2f1SGregory Neil Shapiro if ((args[i] = malloc(len)) == NULL) 363c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "Cannot malloc"); 3643299c2f1SGregory Neil Shapiro snprintf(args[i++], len, "<%s>", *argv); 365c2aa98e2SPeter Wemm } 366c2aa98e2SPeter Wemm argv++; 367d995d2baSGregory Neil Shapiro argc--; 368d995d2baSGregory Neil Shapiro 369d995d2baSGregory Neil Shapiro /* Paranoia check, argc used for args[] bound */ 370d995d2baSGregory Neil Shapiro if (argc < 0) 371d995d2baSGregory Neil Shapiro err(EX_SOFTWARE, "Argument count mismatch"); 372c2aa98e2SPeter Wemm } 373d995d2baSGregory Neil Shapiro args[i] = NULL; 374c2aa98e2SPeter Wemm 3753299c2f1SGregory Neil Shapiro if (debug) 3763299c2f1SGregory Neil Shapiro { 3773299c2f1SGregory Neil Shapiro fprintf(stderr, "Sendmail arguments:\n"); 378d995d2baSGregory Neil Shapiro for (i = 0; args[i] != NULL; i++) 3793299c2f1SGregory Neil Shapiro fprintf(stderr, "\t%s\n", args[i]); 380c2aa98e2SPeter Wemm } 381c2aa98e2SPeter Wemm 382c2aa98e2SPeter Wemm /* 3833299c2f1SGregory Neil Shapiro ** If called with a regular file as standard input, seek to the right 3843299c2f1SGregory Neil Shapiro ** position in the file and just exec sendmail. Could probably skip 3853299c2f1SGregory Neil Shapiro ** skip the stat, but it's not unreasonable to believe that a failed 3863299c2f1SGregory Neil Shapiro ** seek will cause future reads to fail. 387c2aa98e2SPeter Wemm */ 3883299c2f1SGregory Neil Shapiro 3893299c2f1SGregory Neil Shapiro if (!fstat(STDIN_FILENO, &sb) && S_ISREG(sb.st_mode)) 3903299c2f1SGregory Neil Shapiro { 391c2aa98e2SPeter Wemm if (lseek(STDIN_FILENO, offset, SEEK_SET) != offset) 392c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "stdin seek"); 3933299c2f1SGregory Neil Shapiro (void) execv(_PATH_SENDMAIL, args); 394c2aa98e2SPeter Wemm err(EX_OSERR, "%s", _PATH_SENDMAIL); 395c2aa98e2SPeter Wemm } 396c2aa98e2SPeter Wemm 397c2aa98e2SPeter Wemm if (pipe(pdes) < 0) 398c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 399c2aa98e2SPeter Wemm 4003299c2f1SGregory Neil Shapiro switch (pid = FORK()) 4013299c2f1SGregory Neil Shapiro { 402c2aa98e2SPeter Wemm case -1: /* Err. */ 403c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 4043299c2f1SGregory Neil Shapiro /* NOTREACHED */ 4053299c2f1SGregory Neil Shapiro 406c2aa98e2SPeter Wemm case 0: /* Child. */ 4073299c2f1SGregory Neil Shapiro if (pdes[0] != STDIN_FILENO) 4083299c2f1SGregory Neil Shapiro { 409c2aa98e2SPeter Wemm (void) dup2(pdes[0], STDIN_FILENO); 410c2aa98e2SPeter Wemm (void) close(pdes[0]); 411c2aa98e2SPeter Wemm } 412c2aa98e2SPeter Wemm (void) close(pdes[1]); 4133299c2f1SGregory Neil Shapiro (void) execv(_PATH_SENDMAIL, args); 414c2aa98e2SPeter Wemm _exit(127); 415c2aa98e2SPeter Wemm /* NOTREACHED */ 416c2aa98e2SPeter Wemm } 417c2aa98e2SPeter Wemm 418c2aa98e2SPeter Wemm if ((fp = fdopen(pdes[1], "w")) == NULL) 419c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 420c2aa98e2SPeter Wemm (void) close(pdes[0]); 421c2aa98e2SPeter Wemm 422c2aa98e2SPeter Wemm /* Copy the file down the pipe. */ 4233299c2f1SGregory Neil Shapiro do 4243299c2f1SGregory Neil Shapiro { 425c2aa98e2SPeter Wemm (void) fprintf(fp, "%s", lbuf); 426c2aa98e2SPeter Wemm } while (fgets(lbuf, sizeof(lbuf), stdin) != NULL); 427c2aa98e2SPeter Wemm 428c2aa98e2SPeter Wemm if (ferror(stdin)) 4293299c2f1SGregory Neil Shapiro err(EX_TEMPFAIL, "stdin: %s", errstring(errno)); 430c2aa98e2SPeter Wemm 431c2aa98e2SPeter Wemm if (fclose(fp)) 432c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 433c2aa98e2SPeter Wemm 434c2aa98e2SPeter Wemm if ((waitpid(pid, &status, 0)) == -1) 435c2aa98e2SPeter Wemm err(EX_OSERR, "%s", _PATH_SENDMAIL); 436c2aa98e2SPeter Wemm 437c2aa98e2SPeter Wemm if (!WIFEXITED(status)) 4383299c2f1SGregory Neil Shapiro err(EX_OSERR, "%s: did not terminate normally", _PATH_SENDMAIL); 439c2aa98e2SPeter Wemm 440c2aa98e2SPeter Wemm if (WEXITSTATUS(status)) 441c2aa98e2SPeter Wemm err(status, "%s: terminated with %d (non-zero) status", 442c2aa98e2SPeter Wemm _PATH_SENDMAIL, WEXITSTATUS(status)); 443c2aa98e2SPeter Wemm exit(EX_OK); 4443299c2f1SGregory Neil Shapiro /* NOTREACHED */ 4453299c2f1SGregory Neil Shapiro return EX_OK; 446c2aa98e2SPeter Wemm } 447c2aa98e2SPeter Wemm 4483299c2f1SGregory Neil Shapiro static void 449c2aa98e2SPeter Wemm usage() 450c2aa98e2SPeter Wemm { 451c2aa98e2SPeter Wemm (void) fprintf(stderr, "usage: rmail [-T] [-D domain] user ...\n"); 452c2aa98e2SPeter Wemm exit(EX_USAGE); 453c2aa98e2SPeter Wemm } 454c2aa98e2SPeter Wemm 455c2aa98e2SPeter Wemm #ifdef __STDC__ 456c2aa98e2SPeter Wemm # include <stdarg.h> 4573299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 458c2aa98e2SPeter Wemm # include <varargs.h> 4593299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 460c2aa98e2SPeter Wemm 4613299c2f1SGregory Neil Shapiro static void 462c2aa98e2SPeter Wemm #ifdef __STDC__ 463c2aa98e2SPeter Wemm err(int eval, const char *fmt, ...) 4643299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 465c2aa98e2SPeter Wemm err(eval, fmt, va_alist) 466c2aa98e2SPeter Wemm int eval; 467c2aa98e2SPeter Wemm const char *fmt; 468c2aa98e2SPeter Wemm va_dcl 4693299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 470c2aa98e2SPeter Wemm { 471c2aa98e2SPeter Wemm va_list ap; 4723299c2f1SGregory Neil Shapiro #ifdef __STDC__ 473c2aa98e2SPeter Wemm va_start(ap, fmt); 4743299c2f1SGregory Neil Shapiro #else /* __STDC__ */ 475c2aa98e2SPeter Wemm va_start(ap); 4763299c2f1SGregory Neil Shapiro #endif /* __STDC__ */ 477c2aa98e2SPeter Wemm (void) fprintf(stderr, "rmail: "); 478c2aa98e2SPeter Wemm (void) vfprintf(stderr, fmt, ap); 479c2aa98e2SPeter Wemm va_end(ap); 480c2aa98e2SPeter Wemm (void) fprintf(stderr, "\n"); 481c2aa98e2SPeter Wemm exit(eval); 482c2aa98e2SPeter Wemm } 483