1c2aa98e2SPeter Wemm /* 2c2aa98e2SPeter Wemm * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 4c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 5c2aa98e2SPeter Wemm * 6c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 7c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 8c2aa98e2SPeter Wemm * the sendmail distribution. 9c2aa98e2SPeter Wemm * 10c2aa98e2SPeter Wemm */ 11c2aa98e2SPeter Wemm 12c2aa98e2SPeter Wemm #ifndef lint 13c2aa98e2SPeter Wemm static char copyright[] = 14c2aa98e2SPeter Wemm "@(#) Copyright (c) 1988, 1993\n\ 15c2aa98e2SPeter Wemm The Regents of the University of California. All rights reserved.\n"; 16c2aa98e2SPeter Wemm #endif /* not lint */ 17c2aa98e2SPeter Wemm 18c2aa98e2SPeter Wemm #ifndef lint 19c2aa98e2SPeter Wemm static char sccsid[] = "@(#)rmail.c 8.17 (Berkeley) 5/19/98"; 20c2aa98e2SPeter Wemm #endif /* not lint */ 21c2aa98e2SPeter Wemm 22c2aa98e2SPeter Wemm /* 23c2aa98e2SPeter Wemm * RMAIL -- UUCP mail server. 24c2aa98e2SPeter Wemm * 25c2aa98e2SPeter Wemm * This program reads the >From ... remote from ... lines that UUCP is so 26c2aa98e2SPeter Wemm * fond of and turns them into something reasonable. It then execs sendmail 27c2aa98e2SPeter Wemm * with various options built from these lines. 28c2aa98e2SPeter Wemm * 29c2aa98e2SPeter Wemm * The expected syntax is: 30c2aa98e2SPeter Wemm * 31c2aa98e2SPeter Wemm * <user> := [-a-z0-9]+ 32c2aa98e2SPeter Wemm * <date> := ctime format 33c2aa98e2SPeter Wemm * <site> := [-a-z0-9!]+ 34c2aa98e2SPeter Wemm * <blank line> := "^\n$" 35c2aa98e2SPeter Wemm * <from> := "From" <space> <user> <space> <date> 36c2aa98e2SPeter Wemm * [<space> "remote from" <space> <site>] 37c2aa98e2SPeter Wemm * <forward> := ">" <from> 38c2aa98e2SPeter Wemm * msg := <from> <forward>* <blank-line> <body> 39c2aa98e2SPeter Wemm * 40c2aa98e2SPeter Wemm * The output of rmail(8) compresses the <forward> lines into a single 41c2aa98e2SPeter Wemm * from path. 42c2aa98e2SPeter Wemm * 43c2aa98e2SPeter Wemm * The err(3) routine is included here deliberately to make this code 44c2aa98e2SPeter Wemm * a bit more portable. 45c2aa98e2SPeter Wemm */ 46c2aa98e2SPeter Wemm #include <sys/param.h> 47c2aa98e2SPeter Wemm #include <sys/stat.h> 48c2aa98e2SPeter Wemm #include <sys/wait.h> 49c2aa98e2SPeter Wemm 50c2aa98e2SPeter Wemm #include <ctype.h> 51c2aa98e2SPeter Wemm #include <fcntl.h> 52c2aa98e2SPeter Wemm #ifdef BSD4_4 53c2aa98e2SPeter Wemm # define FORK vfork 54c2aa98e2SPeter Wemm # include <paths.h> 55c2aa98e2SPeter Wemm #else 56c2aa98e2SPeter Wemm # define FORK fork 57c2aa98e2SPeter Wemm # ifndef _PATH_SENDMAIL 58c2aa98e2SPeter Wemm # define _PATH_SENDMAIL "/usr/lib/sendmail" 59c2aa98e2SPeter Wemm # endif 60c2aa98e2SPeter Wemm #endif 61c2aa98e2SPeter Wemm #include <stdio.h> 62c2aa98e2SPeter Wemm #include <stdlib.h> 63c2aa98e2SPeter Wemm #include <string.h> 64c2aa98e2SPeter Wemm #include <unistd.h> 65c2aa98e2SPeter Wemm #ifdef EX_OK 66c2aa98e2SPeter Wemm # undef EX_OK /* unistd.h may have another use for this */ 67c2aa98e2SPeter Wemm #endif 68c2aa98e2SPeter Wemm #include <sysexits.h> 69c2aa98e2SPeter Wemm 70c2aa98e2SPeter Wemm #ifndef MAX 71c2aa98e2SPeter Wemm # define MAX(a, b) ((a) < (b) ? (b) : (a)) 72c2aa98e2SPeter Wemm #endif 73c2aa98e2SPeter Wemm 74c2aa98e2SPeter Wemm #ifndef __P 75c2aa98e2SPeter Wemm # ifdef __STDC__ 76c2aa98e2SPeter Wemm # define __P(protos) protos 77c2aa98e2SPeter Wemm # else 78c2aa98e2SPeter Wemm # define __P(protos) () 79c2aa98e2SPeter Wemm # define const 80c2aa98e2SPeter Wemm # endif 81c2aa98e2SPeter Wemm #endif 82c2aa98e2SPeter Wemm 83c2aa98e2SPeter Wemm #if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) 84c2aa98e2SPeter Wemm # define HASSNPRINTF 1 85c2aa98e2SPeter Wemm #endif 86c2aa98e2SPeter Wemm 87c2aa98e2SPeter Wemm #if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) || \ 88c2aa98e2SPeter Wemm defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) 89c2aa98e2SPeter Wemm # ifndef HASSTRERROR 90c2aa98e2SPeter Wemm # define HASSTRERROR 1 /* has strerror(3) */ 91c2aa98e2SPeter Wemm # endif 92c2aa98e2SPeter Wemm #endif 93c2aa98e2SPeter Wemm 94c2aa98e2SPeter Wemm #if !HASSTRERROR 95c2aa98e2SPeter Wemm extern char *strerror __P((int)); 96c2aa98e2SPeter Wemm #endif 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))) 100c2aa98e2SPeter Wemm #endif 101c2aa98e2SPeter Wemm 102c2aa98e2SPeter Wemm #if !HASSNPRINTF 103c2aa98e2SPeter Wemm extern int snprintf __P((char *, size_t, const char *, ...)); 104c2aa98e2SPeter Wemm #endif /* !HASSNPRINTF */ 105c2aa98e2SPeter Wemm 106c2aa98e2SPeter Wemm u_char tTdvect[100]; 107c2aa98e2SPeter Wemm 108c2aa98e2SPeter Wemm void err __P((int, const char *, ...)); 109c2aa98e2SPeter Wemm void usage __P((void)); 110c2aa98e2SPeter Wemm char *xalloc __P((int)); 111c2aa98e2SPeter Wemm 112c2aa98e2SPeter Wemm #define newstr(s) strcpy(xalloc(strlen(s) + 1), s) 113c2aa98e2SPeter Wemm 114c2aa98e2SPeter Wemm char * 115c2aa98e2SPeter Wemm xalloc(sz) 116c2aa98e2SPeter Wemm register int sz; 117c2aa98e2SPeter Wemm { 118c2aa98e2SPeter Wemm register char *p; 119c2aa98e2SPeter Wemm 120c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 121c2aa98e2SPeter Wemm if (sz <= 0) 122c2aa98e2SPeter Wemm sz = 1; 123c2aa98e2SPeter Wemm 124c2aa98e2SPeter Wemm p = malloc((unsigned) sz); 125c2aa98e2SPeter Wemm if (p == NULL) 126c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "out of memory"); 127c2aa98e2SPeter Wemm return (p); 128c2aa98e2SPeter Wemm } 129c2aa98e2SPeter Wemm 130c2aa98e2SPeter Wemm int 131c2aa98e2SPeter Wemm main(argc, argv) 132c2aa98e2SPeter Wemm int argc; 133c2aa98e2SPeter Wemm char *argv[]; 134c2aa98e2SPeter Wemm { 135c2aa98e2SPeter Wemm extern char *optarg; 136c2aa98e2SPeter Wemm extern int errno, optind; 137c2aa98e2SPeter Wemm FILE *fp; 138c2aa98e2SPeter Wemm struct stat sb; 139c2aa98e2SPeter Wemm size_t fplen, fptlen, len; 140c2aa98e2SPeter Wemm off_t offset; 141c2aa98e2SPeter Wemm int ch, debug, i, pdes[2], pid, status; 142c2aa98e2SPeter Wemm char *addrp, *domain, *p, *t; 143c2aa98e2SPeter Wemm char *from_path, *from_sys, *from_user; 144c2aa98e2SPeter Wemm char *args[100], buf[2048], lbuf[2048]; 145c2aa98e2SPeter Wemm 146c2aa98e2SPeter Wemm debug = 0; 147c2aa98e2SPeter Wemm domain = "UUCP"; /* Default "domain". */ 148b2ee1660SPeter Wemm while ((ch = getopt(argc, argv, "D:T")) != -1) 149c2aa98e2SPeter Wemm switch (ch) { 150c2aa98e2SPeter Wemm case 'T': 151c2aa98e2SPeter Wemm debug = 1; 152c2aa98e2SPeter Wemm break; 153c2aa98e2SPeter Wemm case 'D': 154c2aa98e2SPeter Wemm domain = optarg; 155c2aa98e2SPeter Wemm break; 156c2aa98e2SPeter Wemm case '?': 157c2aa98e2SPeter Wemm default: 158c2aa98e2SPeter Wemm usage(); 159c2aa98e2SPeter Wemm } 160c2aa98e2SPeter Wemm argc -= optind; 161c2aa98e2SPeter Wemm argv += optind; 162c2aa98e2SPeter Wemm 163c2aa98e2SPeter Wemm if (argc < 1) 164c2aa98e2SPeter Wemm usage(); 165c2aa98e2SPeter Wemm 166c2aa98e2SPeter Wemm from_path = from_sys = from_user = NULL; 167c2aa98e2SPeter Wemm for (offset = 0;;) { 168c2aa98e2SPeter Wemm 169c2aa98e2SPeter Wemm /* Get and nul-terminate the line. */ 170c2aa98e2SPeter Wemm if (fgets(lbuf, sizeof(lbuf), stdin) == NULL) 171c2aa98e2SPeter Wemm exit (EX_DATAERR); 172c2aa98e2SPeter Wemm if ((p = strchr(lbuf, '\n')) == NULL) 173c2aa98e2SPeter Wemm err(EX_DATAERR, "line too long"); 174c2aa98e2SPeter Wemm *p = '\0'; 175c2aa98e2SPeter Wemm 176c2aa98e2SPeter Wemm /* Parse lines until reach a non-"From" line. */ 177c2aa98e2SPeter Wemm if (!strncmp(lbuf, "From ", 5)) 178c2aa98e2SPeter Wemm addrp = lbuf + 5; 179c2aa98e2SPeter Wemm else if (!strncmp(lbuf, ">From ", 6)) 180c2aa98e2SPeter Wemm addrp = lbuf + 6; 181c2aa98e2SPeter Wemm else if (offset == 0) 182c2aa98e2SPeter Wemm err(EX_DATAERR, 183c2aa98e2SPeter Wemm "missing or empty From line: %s", lbuf); 184c2aa98e2SPeter Wemm else { 185c2aa98e2SPeter Wemm *p = '\n'; 186c2aa98e2SPeter Wemm break; 187c2aa98e2SPeter Wemm } 188c2aa98e2SPeter Wemm 189c2aa98e2SPeter Wemm if (*addrp == '\0') 190c2aa98e2SPeter Wemm err(EX_DATAERR, "corrupted From line: %s", lbuf); 191c2aa98e2SPeter Wemm 192c2aa98e2SPeter Wemm /* Use the "remote from" if it exists. */ 193c2aa98e2SPeter Wemm for (p = addrp; (p = strchr(p + 1, 'r')) != NULL;) 194c2aa98e2SPeter Wemm if (!strncmp(p, "remote from ", 12)) { 195c2aa98e2SPeter Wemm for (t = p += 12; 196c2aa98e2SPeter Wemm *t && !(isascii(*t) && isspace(*t)); ++t); 197c2aa98e2SPeter Wemm *t = '\0'; 198c2aa98e2SPeter Wemm if (debug) 199c2aa98e2SPeter Wemm (void)fprintf(stderr, 200c2aa98e2SPeter Wemm "remote from: %s\n", p); 201c2aa98e2SPeter Wemm break; 202c2aa98e2SPeter Wemm } 203c2aa98e2SPeter Wemm 204c2aa98e2SPeter Wemm /* Else use the string up to the last bang. */ 205c2aa98e2SPeter Wemm if (p == NULL) { 206c2aa98e2SPeter Wemm if (*addrp == '!') 207c2aa98e2SPeter Wemm err(EX_DATAERR, 208c2aa98e2SPeter Wemm "bang starts address: %s", addrp); 209c2aa98e2SPeter Wemm else if ((t = strrchr(addrp, '!')) != NULL) { 210c2aa98e2SPeter Wemm *t = '\0'; 211c2aa98e2SPeter Wemm p = addrp; 212c2aa98e2SPeter Wemm addrp = t + 1; 213c2aa98e2SPeter Wemm if (*addrp == '\0') 214c2aa98e2SPeter Wemm err(EX_DATAERR, 215c2aa98e2SPeter Wemm "corrupted From line: %s", lbuf); 216c2aa98e2SPeter Wemm if (debug) 217c2aa98e2SPeter Wemm (void)fprintf(stderr, "bang: %s\n", p); 218c2aa98e2SPeter Wemm } 219c2aa98e2SPeter Wemm } 220c2aa98e2SPeter Wemm /* 'p' now points to any system string from this line. */ 221c2aa98e2SPeter Wemm if (p != NULL) { 222c2aa98e2SPeter Wemm /* Nul terminate it as necessary. */ 223c2aa98e2SPeter Wemm for (t = p; *t && !(isascii(*t) && isspace(*t)); ++t); 224c2aa98e2SPeter Wemm *t = '\0'; 225c2aa98e2SPeter Wemm 226c2aa98e2SPeter Wemm /* If the first system, copy to the from_sys string. */ 227c2aa98e2SPeter Wemm if (from_sys == NULL) { 228c2aa98e2SPeter Wemm from_sys = newstr(p); 229c2aa98e2SPeter Wemm if (debug) 230c2aa98e2SPeter Wemm (void)fprintf(stderr, 231c2aa98e2SPeter Wemm "from_sys: %s\n", from_sys); 232c2aa98e2SPeter Wemm } 233c2aa98e2SPeter Wemm 234c2aa98e2SPeter Wemm /* Concatenate to the path string. */ 235c2aa98e2SPeter Wemm len = t - p; 236c2aa98e2SPeter Wemm if (from_path == NULL) { 237c2aa98e2SPeter Wemm fplen = 0; 238c2aa98e2SPeter Wemm if ((from_path = malloc(fptlen = 256)) == NULL) 239c2aa98e2SPeter Wemm err(EX_TEMPFAIL, NULL); 240c2aa98e2SPeter Wemm } 241c2aa98e2SPeter Wemm if (fplen + len + 2 > fptlen) { 242c2aa98e2SPeter Wemm fptlen += MAX(fplen + len + 2, 256); 243c2aa98e2SPeter Wemm if ((from_path = 244c2aa98e2SPeter Wemm realloc(from_path, fptlen)) == NULL) 245c2aa98e2SPeter Wemm err(EX_TEMPFAIL, NULL); 246c2aa98e2SPeter Wemm } 247c2aa98e2SPeter Wemm memmove(from_path + fplen, p, len); 248c2aa98e2SPeter Wemm fplen += len; 249c2aa98e2SPeter Wemm from_path[fplen++] = '!'; 250c2aa98e2SPeter Wemm from_path[fplen] = '\0'; 251c2aa98e2SPeter Wemm } 252c2aa98e2SPeter Wemm 253c2aa98e2SPeter Wemm /* Save off from user's address; the last one wins. */ 254c2aa98e2SPeter Wemm for (p = addrp; *p && !(isascii(*p) && isspace(*p)); ++p); 255c2aa98e2SPeter Wemm *p = '\0'; 256c2aa98e2SPeter Wemm if (*addrp == '\0') 257c2aa98e2SPeter Wemm addrp = "<>"; 258c2aa98e2SPeter Wemm if (from_user != NULL) 259c2aa98e2SPeter Wemm free(from_user); 260c2aa98e2SPeter Wemm from_user = newstr(addrp); 261c2aa98e2SPeter Wemm 262c2aa98e2SPeter Wemm if (debug) { 263c2aa98e2SPeter Wemm if (from_path != NULL) 264c2aa98e2SPeter Wemm (void)fprintf(stderr, 265c2aa98e2SPeter Wemm "from_path: %s\n", from_path); 266c2aa98e2SPeter Wemm (void)fprintf(stderr, "from_user: %s\n", from_user); 267c2aa98e2SPeter Wemm } 268c2aa98e2SPeter Wemm 269c2aa98e2SPeter Wemm if (offset != -1) 270c2aa98e2SPeter Wemm offset = (off_t)ftell(stdin); 271c2aa98e2SPeter Wemm } 272c2aa98e2SPeter Wemm 273c2aa98e2SPeter Wemm i = 0; 274c2aa98e2SPeter Wemm args[i++] = _PATH_SENDMAIL; /* Build sendmail's argument list. */ 275c2aa98e2SPeter Wemm args[i++] = "-oee"; /* No errors, just status. */ 276c2aa98e2SPeter Wemm args[i++] = "-odq"; /* Queue it, don't try to deliver. */ 277c2aa98e2SPeter Wemm args[i++] = "-oi"; /* Ignore '.' on a line by itself. */ 278c2aa98e2SPeter Wemm 279c2aa98e2SPeter Wemm /* set from system and protocol used */ 280c2aa98e2SPeter Wemm if (from_sys == NULL) 281c2aa98e2SPeter Wemm (void)snprintf(buf, sizeof(buf), "-p%s", domain); 282c2aa98e2SPeter Wemm else if (strchr(from_sys, '.') == NULL) 283c2aa98e2SPeter Wemm (void)snprintf(buf, sizeof(buf), "-p%s:%s.%s", 284c2aa98e2SPeter Wemm domain, from_sys, domain); 285c2aa98e2SPeter Wemm else 286c2aa98e2SPeter Wemm (void)snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys); 287c2aa98e2SPeter Wemm args[i++] = newstr(buf); 288c2aa98e2SPeter Wemm 289c2aa98e2SPeter Wemm /* Set name of ``from'' person. */ 290c2aa98e2SPeter Wemm (void)snprintf(buf, sizeof(buf), "-f%s%s", 291c2aa98e2SPeter Wemm from_path ? from_path : "", from_user); 292c2aa98e2SPeter Wemm args[i++] = newstr(buf); 293c2aa98e2SPeter Wemm 294c2aa98e2SPeter Wemm /* 295c2aa98e2SPeter Wemm * Don't copy arguments beginning with - as they will be 296c2aa98e2SPeter Wemm * passed to sendmail and could be interpreted as flags. 297c2aa98e2SPeter Wemm * To prevent confusion of sendmail wrap < and > around 298c2aa98e2SPeter Wemm * the address (helps to pass addrs like @gw1,@gw2:aa@bb) 299c2aa98e2SPeter Wemm */ 300c2aa98e2SPeter Wemm while (*argv) { 301c2aa98e2SPeter Wemm if (**argv == '-') 302c2aa98e2SPeter Wemm err(EX_USAGE, "dash precedes argument: %s", *argv); 303c2aa98e2SPeter Wemm if (strchr(*argv, ',') == NULL || strchr(*argv, '<') != NULL) 304c2aa98e2SPeter Wemm args[i++] = *argv; 305c2aa98e2SPeter Wemm else { 306c2aa98e2SPeter Wemm if ((args[i] = malloc(strlen(*argv) + 3)) == NULL) 307c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "Cannot malloc"); 308c2aa98e2SPeter Wemm sprintf (args [i++], "<%s>", *argv); 309c2aa98e2SPeter Wemm } 310c2aa98e2SPeter Wemm argv++; 311c2aa98e2SPeter Wemm } 312c2aa98e2SPeter Wemm args[i] = 0; 313c2aa98e2SPeter Wemm 314c2aa98e2SPeter Wemm if (debug) { 315c2aa98e2SPeter Wemm (void)fprintf(stderr, "Sendmail arguments:\n"); 316c2aa98e2SPeter Wemm for (i = 0; args[i]; i++) 317c2aa98e2SPeter Wemm (void)fprintf(stderr, "\t%s\n", args[i]); 318c2aa98e2SPeter Wemm } 319c2aa98e2SPeter Wemm 320c2aa98e2SPeter Wemm /* 321c2aa98e2SPeter Wemm * If called with a regular file as standard input, seek to the right 322c2aa98e2SPeter Wemm * position in the file and just exec sendmail. Could probably skip 323c2aa98e2SPeter Wemm * skip the stat, but it's not unreasonable to believe that a failed 324c2aa98e2SPeter Wemm * seek will cause future reads to fail. 325c2aa98e2SPeter Wemm */ 326c2aa98e2SPeter Wemm if (!fstat(STDIN_FILENO, &sb) && S_ISREG(sb.st_mode)) { 327c2aa98e2SPeter Wemm if (lseek(STDIN_FILENO, offset, SEEK_SET) != offset) 328c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "stdin seek"); 329c2aa98e2SPeter Wemm execv(_PATH_SENDMAIL, args); 330c2aa98e2SPeter Wemm err(EX_OSERR, "%s", _PATH_SENDMAIL); 331c2aa98e2SPeter Wemm } 332c2aa98e2SPeter Wemm 333c2aa98e2SPeter Wemm if (pipe(pdes) < 0) 334c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 335c2aa98e2SPeter Wemm 336c2aa98e2SPeter Wemm switch (pid = FORK()) { 337c2aa98e2SPeter Wemm case -1: /* Err. */ 338c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 339c2aa98e2SPeter Wemm case 0: /* Child. */ 340c2aa98e2SPeter Wemm if (pdes[0] != STDIN_FILENO) { 341c2aa98e2SPeter Wemm (void)dup2(pdes[0], STDIN_FILENO); 342c2aa98e2SPeter Wemm (void)close(pdes[0]); 343c2aa98e2SPeter Wemm } 344c2aa98e2SPeter Wemm (void)close(pdes[1]); 345c2aa98e2SPeter Wemm execv(_PATH_SENDMAIL, args); 346c2aa98e2SPeter Wemm _exit(127); 347c2aa98e2SPeter Wemm /* NOTREACHED */ 348c2aa98e2SPeter Wemm } 349c2aa98e2SPeter Wemm 350c2aa98e2SPeter Wemm if ((fp = fdopen(pdes[1], "w")) == NULL) 351c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 352c2aa98e2SPeter Wemm (void)close(pdes[0]); 353c2aa98e2SPeter Wemm 354c2aa98e2SPeter Wemm /* Copy the file down the pipe. */ 355c2aa98e2SPeter Wemm do { 356c2aa98e2SPeter Wemm (void)fprintf(fp, "%s", lbuf); 357c2aa98e2SPeter Wemm } while (fgets(lbuf, sizeof(lbuf), stdin) != NULL); 358c2aa98e2SPeter Wemm 359c2aa98e2SPeter Wemm if (ferror(stdin)) 360c2aa98e2SPeter Wemm err(EX_TEMPFAIL, "stdin: %s", strerror(errno)); 361c2aa98e2SPeter Wemm 362c2aa98e2SPeter Wemm if (fclose(fp)) 363c2aa98e2SPeter Wemm err(EX_OSERR, NULL); 364c2aa98e2SPeter Wemm 365c2aa98e2SPeter Wemm if ((waitpid(pid, &status, 0)) == -1) 366c2aa98e2SPeter Wemm err(EX_OSERR, "%s", _PATH_SENDMAIL); 367c2aa98e2SPeter Wemm 368c2aa98e2SPeter Wemm if (!WIFEXITED(status)) 369c2aa98e2SPeter Wemm err(EX_OSERR, 370c2aa98e2SPeter Wemm "%s: did not terminate normally", _PATH_SENDMAIL); 371c2aa98e2SPeter Wemm 372c2aa98e2SPeter Wemm if (WEXITSTATUS(status)) 373c2aa98e2SPeter Wemm err(status, "%s: terminated with %d (non-zero) status", 374c2aa98e2SPeter Wemm _PATH_SENDMAIL, WEXITSTATUS(status)); 375c2aa98e2SPeter Wemm exit(EX_OK); 376c2aa98e2SPeter Wemm } 377c2aa98e2SPeter Wemm 378c2aa98e2SPeter Wemm void 379c2aa98e2SPeter Wemm usage() 380c2aa98e2SPeter Wemm { 381c2aa98e2SPeter Wemm (void)fprintf(stderr, "usage: rmail [-T] [-D domain] user ...\n"); 382c2aa98e2SPeter Wemm exit(EX_USAGE); 383c2aa98e2SPeter Wemm } 384c2aa98e2SPeter Wemm 385c2aa98e2SPeter Wemm #ifdef __STDC__ 386c2aa98e2SPeter Wemm #include <stdarg.h> 387c2aa98e2SPeter Wemm #else 388c2aa98e2SPeter Wemm #include <varargs.h> 389c2aa98e2SPeter Wemm #endif 390c2aa98e2SPeter Wemm 391c2aa98e2SPeter Wemm void 392c2aa98e2SPeter Wemm #ifdef __STDC__ 393c2aa98e2SPeter Wemm err(int eval, const char *fmt, ...) 394c2aa98e2SPeter Wemm #else 395c2aa98e2SPeter Wemm err(eval, fmt, va_alist) 396c2aa98e2SPeter Wemm int eval; 397c2aa98e2SPeter Wemm const char *fmt; 398c2aa98e2SPeter Wemm va_dcl 399c2aa98e2SPeter Wemm #endif 400c2aa98e2SPeter Wemm { 401c2aa98e2SPeter Wemm va_list ap; 402c2aa98e2SPeter Wemm #if __STDC__ 403c2aa98e2SPeter Wemm va_start(ap, fmt); 404c2aa98e2SPeter Wemm #else 405c2aa98e2SPeter Wemm va_start(ap); 406c2aa98e2SPeter Wemm #endif 407c2aa98e2SPeter Wemm (void)fprintf(stderr, "rmail: "); 408c2aa98e2SPeter Wemm (void)vfprintf(stderr, fmt, ap); 409c2aa98e2SPeter Wemm va_end(ap); 410c2aa98e2SPeter Wemm (void)fprintf(stderr, "\n"); 411c2aa98e2SPeter Wemm exit(eval); 412c2aa98e2SPeter Wemm } 413c2aa98e2SPeter Wemm 414c2aa98e2SPeter Wemm #if !HASSTRERROR 415c2aa98e2SPeter Wemm 416c2aa98e2SPeter Wemm char * 417c2aa98e2SPeter Wemm strerror(eno) 418c2aa98e2SPeter Wemm int eno; 419c2aa98e2SPeter Wemm { 420c2aa98e2SPeter Wemm extern int sys_nerr; 421c2aa98e2SPeter Wemm extern char *sys_errlist[]; 422c2aa98e2SPeter Wemm static char ebuf[60]; 423c2aa98e2SPeter Wemm 424c2aa98e2SPeter Wemm if (eno >= 0 && eno < sys_nerr) 425c2aa98e2SPeter Wemm return sys_errlist[eno]; 426c2aa98e2SPeter Wemm (void) sprintf(ebuf, "Error %d", eno); 427c2aa98e2SPeter Wemm return ebuf; 428c2aa98e2SPeter Wemm } 429c2aa98e2SPeter Wemm 430c2aa98e2SPeter Wemm #endif /* !HASSTRERROR */ 431