11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 311590Srgrimesstatic char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3774769Smikeh#if 0 3888150Smikehstatic char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/20/95"; 3974769Smikeh#endif 401590Srgrimes#endif /* not lint */ 4199112Sobrien#include <sys/cdefs.h> 4299112Sobrien__FBSDID("$FreeBSD$"); 431590Srgrimes 441590Srgrimes#include "rcv.h" 451590Srgrimes#include <fcntl.h> 461590Srgrimes#include "extern.h" 471590Srgrimes 481590Srgrimes/* 491590Srgrimes * Mail -- a mail program 501590Srgrimes * 511590Srgrimes * Startup -- interface with user. 521590Srgrimes */ 531590Srgrimes 54173439Sddsstatic jmp_buf hdrjmp; 551590Srgrimes 5677274Smikehextern const char *version; 5777274Smikeh 581590Srgrimesint 59216564Scharniermain(int argc, char *argv[]) 601590Srgrimes{ 6177274Smikeh int i; 621590Srgrimes struct name *to, *cc, *bcc, *smopts; 6332189Sjoerg char *subject, *replyto; 6488150Smikeh char *ef, *rc; 651590Srgrimes char nosrc = 0; 661590Srgrimes sig_t prevint; 671590Srgrimes 681590Srgrimes /* 691590Srgrimes * Set up a reasonable environment. 701590Srgrimes * Figure out whether we are being run interactively, 711590Srgrimes * start the SIGCHLD catcher, and so forth. 721590Srgrimes */ 7377274Smikeh (void)signal(SIGCHLD, sigchild); 741590Srgrimes if (isatty(0)) 751590Srgrimes assign("interactive", ""); 761590Srgrimes image = -1; 771590Srgrimes /* 781590Srgrimes * Now, determine how we are being used. 791590Srgrimes * We successively pick off - flags. 801590Srgrimes * If there is anything left, it is the base of the list 811590Srgrimes * of users to mail to. Argp will be set to point to the 821590Srgrimes * first of these users. 831590Srgrimes */ 8477274Smikeh ef = NULL; 8577274Smikeh to = NULL; 8677274Smikeh cc = NULL; 8777274Smikeh bcc = NULL; 8877274Smikeh smopts = NULL; 8977274Smikeh subject = NULL; 90126415Smikeh while ((i = getopt(argc, argv, "FEHINT:b:c:edfins:u:v")) != -1) { 911590Srgrimes switch (i) { 921590Srgrimes case 'T': 931590Srgrimes /* 941590Srgrimes * Next argument is temp file to write which 951590Srgrimes * articles have been read/deleted for netnews. 961590Srgrimes */ 971590Srgrimes Tflag = optarg; 9874769Smikeh if ((i = open(Tflag, O_CREAT | O_TRUNC | O_WRONLY, 9977274Smikeh 0600)) < 0) 10074769Smikeh err(1, "%s", Tflag); 10177274Smikeh (void)close(i); 1021590Srgrimes break; 1031590Srgrimes case 'u': 1041590Srgrimes /* 1051590Srgrimes * Next argument is person to pretend to be. 1061590Srgrimes */ 1071590Srgrimes myname = optarg; 10877274Smikeh unsetenv("MAIL"); 1091590Srgrimes break; 1101590Srgrimes case 'i': 1111590Srgrimes /* 1121590Srgrimes * User wants to ignore interrupts. 1131590Srgrimes * Set the variable "ignore" 1141590Srgrimes */ 1151590Srgrimes assign("ignore", ""); 1161590Srgrimes break; 1171590Srgrimes case 'd': 1181590Srgrimes debug++; 1191590Srgrimes break; 120126415Smikeh case 'e': 121126415Smikeh /* 122126415Smikeh * User wants to check mail and exit. 123126415Smikeh */ 124126415Smikeh assign("checkmode", ""); 125126415Smikeh break; 126126415Smikeh case 'H': 127126415Smikeh /* 128126415Smikeh * User wants a header summary only. 129126415Smikeh */ 130126415Smikeh assign("headersummary", ""); 131126415Smikeh break; 132126415Smikeh case 'F': 133126415Smikeh /* 134126415Smikeh * User wants to record messages to files 135126415Smikeh * named after first recipient username. 136126415Smikeh */ 137126415Smikeh assign("recordrecip", ""); 138126415Smikeh break; 1391590Srgrimes case 's': 1401590Srgrimes /* 1411590Srgrimes * Give a subject field for sending from 1421590Srgrimes * non terminal 1431590Srgrimes */ 1441590Srgrimes subject = optarg; 1451590Srgrimes break; 1461590Srgrimes case 'f': 1471590Srgrimes /* 1481590Srgrimes * User is specifying file to "edit" with Mail, 1491590Srgrimes * as opposed to reading system mailbox. 1501590Srgrimes * If no argument is given after -f, we read his 1511590Srgrimes * mbox file. 1521590Srgrimes * 1531590Srgrimes * getopt() can't handle optional arguments, so here 1541590Srgrimes * is an ugly hack to get around it. 1551590Srgrimes */ 15677274Smikeh if ((argv[optind] != NULL) && (argv[optind][0] != '-')) 1571590Srgrimes ef = argv[optind++]; 1581590Srgrimes else 1591590Srgrimes ef = "&"; 1601590Srgrimes break; 1611590Srgrimes case 'n': 1621590Srgrimes /* 1631590Srgrimes * User doesn't want to source /usr/lib/Mail.rc 1641590Srgrimes */ 1651590Srgrimes nosrc++; 1661590Srgrimes break; 1671590Srgrimes case 'N': 1681590Srgrimes /* 1691590Srgrimes * Avoid initial header printing. 1701590Srgrimes */ 1711590Srgrimes assign("noheader", ""); 1721590Srgrimes break; 1731590Srgrimes case 'v': 1741590Srgrimes /* 1751590Srgrimes * Send mailer verbose flag 1761590Srgrimes */ 1771590Srgrimes assign("verbose", ""); 1781590Srgrimes break; 1791590Srgrimes case 'I': 1801590Srgrimes /* 1811590Srgrimes * We're interactive 1821590Srgrimes */ 1831590Srgrimes assign("interactive", ""); 1841590Srgrimes break; 1851590Srgrimes case 'c': 1861590Srgrimes /* 1871590Srgrimes * Get Carbon Copy Recipient list 1881590Srgrimes */ 1891590Srgrimes cc = cat(cc, nalloc(optarg, GCC)); 1901590Srgrimes break; 1911590Srgrimes case 'b': 1921590Srgrimes /* 1931590Srgrimes * Get Blind Carbon Copy Recipient list 1941590Srgrimes */ 1951590Srgrimes bcc = cat(bcc, nalloc(optarg, GBCC)); 1961590Srgrimes break; 19778904Smikeh case 'E': 19878904Smikeh /* 19978904Smikeh * Don't send empty files. 20078904Smikeh */ 20178904Smikeh assign("dontsendempty", ""); 20278904Smikeh break; 2031590Srgrimes case '?': 20474769Smikeh fprintf(stderr, "\ 205151053SyarUsage: %s [-dEiInv] [-s subject] [-c cc-addr] [-b bcc-addr] [-F] to-addr ...\n\ 206151053Syar %*s [-sendmail-option ...]\n\ 207151053Syar %s [-dEHiInNv] [-F] -f [name]\n\ 208151053Syar %s [-dEHiInNv] [-F] [-u user]\n\ 209228647Sdim %s [-d] -e [-f name]\n", __progname, (int)strlen(__progname), "", 210151053Syar __progname, __progname, __progname); 2111590Srgrimes exit(1); 2121590Srgrimes } 2131590Srgrimes } 21477274Smikeh for (i = optind; (argv[i] != NULL) && (*argv[i] != '-'); i++) 2151590Srgrimes to = cat(to, nalloc(argv[i], GTO)); 21677274Smikeh for (; argv[i] != NULL; i++) 2171590Srgrimes smopts = cat(smopts, nalloc(argv[i], 0)); 2181590Srgrimes /* 2191590Srgrimes * Check for inconsistent arguments. 2201590Srgrimes */ 22177274Smikeh if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL)) 22274769Smikeh errx(1, "You must specify direct recipients with -s, -c, or -b."); 22377274Smikeh if (ef != NULL && to != NULL) 22474769Smikeh errx(1, "Cannot give -f and people to send to."); 2251590Srgrimes tinit(); 2261590Srgrimes setscreensize(); 2271590Srgrimes input = stdin; 2281590Srgrimes rcvmode = !to; 2291590Srgrimes spreserve(); 23020778Sjkh if (!nosrc) { 23120778Sjkh char *s, *path_rc; 23220778Sjkh 23374769Smikeh if ((path_rc = malloc(sizeof(_PATH_MASTER_RC))) == NULL) 23474769Smikeh err(1, "malloc(path_rc) failed"); 23520778Sjkh 23620778Sjkh strcpy(path_rc, _PATH_MASTER_RC); 23720778Sjkh while ((s = strsep(&path_rc, ":")) != NULL) 23820778Sjkh if (*s != '\0') 23920778Sjkh load(s); 24020778Sjkh } 2411590Srgrimes /* 2421590Srgrimes * Expand returns a savestr, but load only uses the file name 2431590Srgrimes * for fopen, so it's safe to do this. 2441590Srgrimes */ 24588150Smikeh if ((rc = getenv("MAILRC")) == NULL) 24688150Smikeh rc = "~/.mailrc"; 24788150Smikeh load(expand(rc)); 24878193Smikeh 24978193Smikeh replyto = value("REPLYTO"); 2501590Srgrimes if (!rcvmode) { 25132189Sjoerg mail(to, cc, bcc, smopts, subject, replyto); 2521590Srgrimes /* 2531590Srgrimes * why wait? 2541590Srgrimes */ 2551590Srgrimes exit(senderr); 2561590Srgrimes } 257126415Smikeh 258126415Smikeh if(value("checkmode") != NULL) { 259126415Smikeh if (ef == NULL) 260126415Smikeh ef = "%"; 261126415Smikeh if (setfile(ef) <= 0) 262229655Suqs /* Either an error has occurred, or no mail */ 263126415Smikeh exit(1); 264126415Smikeh else 265126415Smikeh exit(0); 266126415Smikeh /* NOTREACHED */ 267126415Smikeh } 268126415Smikeh 2691590Srgrimes /* 2701590Srgrimes * Ok, we are reading mail. 2711590Srgrimes * Decide whether we are editing a mailbox or reading 2721590Srgrimes * the system mailbox, and open up the right stuff. 2731590Srgrimes */ 27477274Smikeh if (ef == NULL) 2751590Srgrimes ef = "%"; 2761590Srgrimes if (setfile(ef) < 0) 2771590Srgrimes exit(1); /* error already reported */ 2781590Srgrimes if (setjmp(hdrjmp) == 0) { 2791590Srgrimes if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN) 28077274Smikeh (void)signal(SIGINT, hdrstop); 28177274Smikeh if (value("quiet") == NULL) 2821590Srgrimes printf("Mail version %s. Type ? for help.\n", 2831590Srgrimes version); 2841590Srgrimes announce(); 28577274Smikeh (void)fflush(stdout); 28677274Smikeh (void)signal(SIGINT, prevint); 2871590Srgrimes } 288126415Smikeh 289126415Smikeh /* If we were in header summary mode, it's time to exit. */ 290126415Smikeh if (value("headersummary") != NULL) 291126415Smikeh exit(0); 292126415Smikeh 2931590Srgrimes commands(); 29477274Smikeh (void)signal(SIGHUP, SIG_IGN); 29577274Smikeh (void)signal(SIGINT, SIG_IGN); 29677274Smikeh (void)signal(SIGQUIT, SIG_IGN); 2971590Srgrimes quit(); 2981590Srgrimes exit(0); 2991590Srgrimes} 3001590Srgrimes 3011590Srgrimes/* 3021590Srgrimes * Interrupt printing of the headers. 3031590Srgrimes */ 30477274Smikeh/*ARGSUSED*/ 3051590Srgrimesvoid 306216564Scharnierhdrstop(int signo __unused) 3071590Srgrimes{ 3081590Srgrimes 30977274Smikeh (void)fflush(stdout); 3101590Srgrimes fprintf(stderr, "\nInterrupt\n"); 3111590Srgrimes longjmp(hdrjmp, 1); 3121590Srgrimes} 3131590Srgrimes 3141590Srgrimes/* 3151590Srgrimes * Compute what the screen size for printing headers should be. 3161590Srgrimes * We use the following algorithm for the height: 3171590Srgrimes * If baud rate < 1200, use 9 3181590Srgrimes * If baud rate = 1200, use 14 3191590Srgrimes * If baud rate > 1200, use 24 or ws_row 3201590Srgrimes * Width is either 80 or ws_col; 3211590Srgrimes */ 3221590Srgrimesvoid 323216564Scharniersetscreensize(void) 3241590Srgrimes{ 32588150Smikeh struct termios tbuf; 3261590Srgrimes struct winsize ws; 32788150Smikeh speed_t speed; 3281590Srgrimes 32977274Smikeh if (ioctl(1, TIOCGWINSZ, (char *)&ws) < 0) 3301590Srgrimes ws.ws_col = ws.ws_row = 0; 33188150Smikeh if (tcgetattr(1, &tbuf) < 0) 33217678Speter speed = B9600; 33388150Smikeh else 33488150Smikeh speed = cfgetospeed(&tbuf); 33517678Speter if (speed < B1200) 3361590Srgrimes screenheight = 9; 33717678Speter else if (speed == B1200) 3381590Srgrimes screenheight = 14; 3391590Srgrimes else if (ws.ws_row != 0) 3401590Srgrimes screenheight = ws.ws_row; 3411590Srgrimes else 3421590Srgrimes screenheight = 24; 3431590Srgrimes if ((realscreenheight = ws.ws_row) == 0) 3441590Srgrimes realscreenheight = 24; 3451590Srgrimes if ((screenwidth = ws.ws_col) == 0) 3461590Srgrimes screenwidth = 80; 3471590Srgrimes} 348