Annotation of CVSROOT/mailsend.c, Revision 1.1
1.1 ! maekawa 1: /*-
! 2: * Copyright (c) 1999, Peter Wemm <peter@netplex.com.au>
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 17: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 24: * SUCH DAMAGE.
! 25: *
! 26: * $FreeBSD: CVSROOT-src/freebsd/mailsend.c,v 1.6 2001/11/15 14:19:21 joe Exp $
! 27: * $OpenXM$
! 28: */
! 29:
! 30: /*
! 31: * Actually, this is a hack that I've used for a zillion years
! 32: * elsewhere originating on a SVR4 machine. But hey, it works.
! 33: */
! 34:
! 35: #include <stdio.h>
! 36: #include <stdlib.h>
! 37: #include <unistd.h>
! 38: #include <string.h>
! 39: #include <pwd.h>
! 40: #include <sys/types.h>
! 41: #include <sys/param.h>
! 42: #include <sys/wait.h>
! 43: #include <paths.h>
! 44: #include <time.h>
! 45:
! 46:
! 47: char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
! 48: char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
! 49: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
! 50:
! 51: char *Prog;
! 52:
! 53: static int
! 54: writestr(int fd, char *buf)
! 55: {
! 56: return write(fd, buf, strlen(buf));
! 57: }
! 58:
! 59: static void
! 60: usage(void)
! 61: {
! 62: writestr(2, "Usage: ");
! 63: writestr(2, Prog);
! 64: writestr(2, " [ -s subject ] [ -r reply-to ] "
! 65: "[ -f from ] [ -f From: ]..\n");
! 66: writestr(2, " [ -b bcc ] [ -c cc ] [-H] [-I/-B/-Q] "
! 67: "[-v] address [address]...\n");
! 68: exit(1);
! 69: }
! 70:
! 71: static char *
! 72: makerfc822date(time_t now)
! 73: {
! 74: struct tm *tm;
! 75: static char buf[1024];
! 76: time_t tzo;
! 77:
! 78: tm = localtime(&now);
! 79:
! 80: tzo = tm->tm_gmtoff;
! 81:
! 82: tzo = tzo / 60; /* minutes */
! 83: tzo = (tzo % 60) + (tzo / 60 * 100);
! 84:
! 85: snprintf(buf, sizeof(buf), "%s, %d %s %d %02d:%02d:%02d %+05ld (%s)",
! 86: wday[tm->tm_wday], tm->tm_mday, mon[tm->tm_mon],
! 87: tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
! 88: tm->tm_sec, tzo, tm->tm_zone);
! 89: return buf;
! 90: }
! 91:
! 92:
! 93:
! 94: int
! 95: main(int ac, char **av)
! 96: {
! 97: int c;
! 98: int i;
! 99: pid_t pid;
! 100: int pfd[2];
! 101: char *smvec[1024];
! 102: char **vec = smvec;
! 103: char buf[1024];
! 104: char Frombuf[256]; /* Long enough */
! 105: char frombuf[256]; /* Long enough */
! 106: char gecos[256]; /* Long enough */
! 107: char *s;
! 108:
! 109: char *subj = NULL;
! 110: char *reply = NULL;
! 111: char *from = NULL;
! 112: char *From = NULL;
! 113: char *cc = NULL;
! 114: char *bcc = NULL;
! 115: char *delmode = NULL;
! 116: char *verbose = NULL;
! 117: char *hostname = NULL;
! 118: int headers = 0;
! 119:
! 120: struct passwd *pw;
! 121:
! 122: Prog = av[0];
! 123:
! 124: while ((c = getopt(ac, av, "s:f:F:h:r:c:b:IBQHv")) != EOF) {
! 125: switch (c) {
! 126:
! 127: case 's': /* -s Subject: */
! 128: if (subj)
! 129: usage();
! 130: subj = optarg;
! 131: break;
! 132:
! 133: case 'f': /* -f From_ */
! 134: if (from)
! 135: usage();
! 136: from = optarg;
! 137: break;
! 138:
! 139: case 'F': /* -F From: */
! 140: if (From)
! 141: usage();
! 142: From = optarg;
! 143: break;
! 144:
! 145: case 'h': /* -h hostname */
! 146: if (hostname)
! 147: usage();
! 148: hostname = optarg;
! 149: break;
! 150:
! 151: case 'H': /* -H = headers coming in via stdin too */
! 152: headers++;
! 153: break;
! 154:
! 155: case 'r': /* -r Reply-To: */
! 156: if (reply)
! 157: usage();
! 158: reply = optarg;
! 159: break;
! 160:
! 161: case 'b': /* -b Bcc: */
! 162: if (bcc)
! 163: usage();
! 164: bcc = optarg;
! 165: break;
! 166:
! 167: case 'c': /* -b cc: */
! 168: if (cc)
! 169: usage();
! 170: cc = optarg;
! 171: break;
! 172:
! 173: case 'I': /* -I interactive delivery */
! 174: delmode = "-odi";
! 175: break;
! 176:
! 177: case 'B': /* -B background delivery */
! 178: delmode = "-odb";
! 179: break;
! 180:
! 181: case 'Q': /* -Q queue up only */
! 182: delmode = "-odq";
! 183: break;
! 184:
! 185: case 'v':
! 186: verbose = "-v";
! 187: break;
! 188:
! 189: default:
! 190: case '?': /* err */
! 191: writestr(2, "Unknown switch: '");
! 192: buf[0] = optopt;
! 193: buf[1] = '\0';
! 194: writestr(2, buf);
! 195: writestr(2, "'\n");
! 196: usage();
! 197: break;
! 198: }
! 199: }
! 200: ac -= optind;
! 201: av += optind;
! 202: if (ac < 1) {
! 203: writestr(2, "you must supply an address!\n");
! 204: usage();
! 205: }
! 206:
! 207: if (hostname == NULL) {
! 208: gethostname(buf, sizeof(buf));
! 209: buf[sizeof(buf)-1] = '\0'; /* academic.. */
! 210: hostname = buf;
! 211: }
! 212: Frombuf[0] = '\0';
! 213:
! 214: if (From) {
! 215: /* From@hostname */
! 216: snprintf(Frombuf, sizeof(Frombuf), "%s@%s", From, hostname);
! 217: pw = getpwnam(From);
! 218: } else {
! 219: pw = getpwuid(getuid());
! 220: }
! 221: if (pw && hostname == buf) {
! 222: if (pw->pw_gecos) {
! 223: strncpy(gecos, pw->pw_gecos, sizeof(gecos) - 1);
! 224: gecos[sizeof(gecos) - 1] = '\0';
! 225: if ((s = strchr(gecos, ',')))
! 226: *s = '\0';
! 227: if ((s = strchr(gecos, ';')))
! 228: *s = '\0';
! 229: snprintf(Frombuf, sizeof(Frombuf), "%s <%s@%s>",
! 230: gecos, pw->pw_name, hostname);
! 231: } else {
! 232: /* From@hostname */
! 233: snprintf(Frombuf, sizeof(Frombuf), "%s@%s",
! 234: pw->pw_name, hostname);
! 235: }
! 236: }
! 237: endpwent();
! 238: if (verbose) {
! 239: writestr(2, "From: ");
! 240: writestr(2, Frombuf);
! 241: writestr(2, "\n");
! 242: }
! 243:
! 244: *vec++ = "sendmail";
! 245: *vec++ = "-oi";
! 246: *vec++ = "-oem";
! 247:
! 248: if (delmode) {
! 249: *vec++ = delmode;
! 250: }
! 251:
! 252: if (verbose) {
! 253: *vec++ = verbose;
! 254: }
! 255:
! 256: if (from) {
! 257: *vec++ = "-f";
! 258: snprintf(frombuf, sizeof(frombuf), "%s@%s", from, hostname);
! 259: *vec++ = frombuf;
! 260: }
! 261:
! 262: for (i = 0; i < ac; i++)
! 263: *vec++ = av[i];
! 264:
! 265: if (bcc)
! 266: *vec++ = bcc;
! 267:
! 268: *vec++ = NULL;
! 269:
! 270: if (verbose) {
! 271: writestr(1, "Executing:");
! 272: vec = smvec;
! 273: while (*vec) {
! 274: writestr(1, " ");
! 275: writestr(1, *vec);
! 276: vec++;
! 277: }
! 278: writestr(1, "\n");
! 279: }
! 280:
! 281:
! 282: if (pipe(pfd) < 0) {
! 283: perror("pipe");
! 284: exit(1);
! 285: }
! 286:
! 287: pid = fork();
! 288:
! 289: switch(pid) {
! 290:
! 291: case 0: /* child */
! 292: close(0);
! 293: dup(pfd[0]);
! 294: for (i = 3; i < 64; i++)
! 295: close(i);
! 296: execv(_PATH_SENDMAIL, smvec);
! 297: perror(_PATH_SENDMAIL);
! 298: _exit(1);
! 299: break;
! 300:
! 301: case -1: /* error */
! 302: perror("fork");
! 303: exit(1);
! 304: break;
! 305:
! 306: default: /* parent */
! 307: close(pfd[0]);
! 308: break;
! 309: }
! 310:
! 311: if (Frombuf[0]) {
! 312: writestr(pfd[1], "From: ");
! 313: writestr(pfd[1], Frombuf);
! 314: writestr(pfd[1], "\n");
! 315: }
! 316: writestr(pfd[1], "Date: ");
! 317: writestr(pfd[1], makerfc822date(time(0)));
! 318: writestr(pfd[1], "\n");
! 319:
! 320: if (subj) {
! 321: writestr(pfd[1], "Subject: ");
! 322: writestr(pfd[1], subj);
! 323: writestr(pfd[1], "\n");
! 324: }
! 325: if (reply) {
! 326: writestr(pfd[1], "Reply-To: ");
! 327: writestr(pfd[1], reply);
! 328: writestr(pfd[1], "\n");
! 329: }
! 330: if (cc) {
! 331: writestr(pfd[1], "Cc: ");
! 332: writestr(pfd[1], cc);
! 333: writestr(pfd[1], "\n");
! 334: }
! 335:
! 336: writestr(pfd[1], "To: ");
! 337: writestr(pfd[1], av[0]);
! 338:
! 339: for (i = 1; i < ac; i++) {
! 340: writestr(pfd[1], ", ");
! 341: writestr(pfd[1], av[i]);
! 342: }
! 343: writestr(pfd[1], "\n");
! 344:
! 345: /* Headers from stdin */
! 346: if (!headers)
! 347: writestr(pfd[1], "\n");
! 348:
! 349: while ((c = read(0, buf, sizeof(buf))) > 0) {
! 350: write(pfd[1], buf, c);
! 351: }
! 352:
! 353: close(pfd[1]);
! 354:
! 355: alarm(600); /* drop dead in 10 minutes */
! 356:
! 357: while (wait(NULL) > 0)
! 358: ;
! 359:
! 360: exit(0);
! 361: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>