19b50d902SRodney W. Grimes /* 29b50d902SRodney W. Grimes * Copyright (c) 1980, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 149b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 159b50d902SRodney W. Grimes * without specific prior written permission. 169b50d902SRodney W. Grimes * 179b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 189b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 219b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279b50d902SRodney W. Grimes * SUCH DAMAGE. 289b50d902SRodney W. Grimes */ 299b50d902SRodney W. Grimes 309b50d902SRodney W. Grimes #ifndef lint 319b50d902SRodney W. Grimes static char copyright[] = 329b50d902SRodney W. Grimes "@(#) Copyright (c) 1980, 1993\n\ 339b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 349b50d902SRodney W. Grimes #endif /* not lint */ 359b50d902SRodney W. Grimes 369b50d902SRodney W. Grimes #ifndef lint 370c3a8314SMike Heffner #if 0 38856f23edSMike Heffner static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/20/95"; 390c3a8314SMike Heffner #endif 409b50d902SRodney W. Grimes #endif /* not lint */ 41e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 42e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 439b50d902SRodney W. Grimes 449b50d902SRodney W. Grimes #include "rcv.h" 459b50d902SRodney W. Grimes #include <fcntl.h> 469b50d902SRodney W. Grimes #include "extern.h" 479b50d902SRodney W. Grimes 489b50d902SRodney W. Grimes /* 499b50d902SRodney W. Grimes * Mail -- a mail program 509b50d902SRodney W. Grimes * 519b50d902SRodney W. Grimes * Startup -- interface with user. 529b50d902SRodney W. Grimes */ 539b50d902SRodney W. Grimes 54e7d53813SDiomidis Spinellis static jmp_buf hdrjmp; 559b50d902SRodney W. Grimes 569ce73e90SMike Heffner extern const char *version; 579ce73e90SMike Heffner 589b50d902SRodney W. Grimes int 596d8484b0SPhilippe Charnier main(int argc, char *argv[]) 609b50d902SRodney W. Grimes { 619ce73e90SMike Heffner int i; 629b50d902SRodney W. Grimes struct name *to, *cc, *bcc, *smopts; 6399bd6601SJoerg Wunsch char *subject, *replyto; 64856f23edSMike Heffner char *ef, *rc; 659b50d902SRodney W. Grimes char nosrc = 0; 669b50d902SRodney W. Grimes sig_t prevint; 679b50d902SRodney W. Grimes 689b50d902SRodney W. Grimes /* 699b50d902SRodney W. Grimes * Set up a reasonable environment. 709b50d902SRodney W. Grimes * Figure out whether we are being run interactively, 719b50d902SRodney W. Grimes * start the SIGCHLD catcher, and so forth. 729b50d902SRodney W. Grimes */ 739b50d902SRodney W. Grimes (void)signal(SIGCHLD, sigchild); 749b50d902SRodney W. Grimes if (isatty(0)) 759b50d902SRodney W. Grimes assign("interactive", ""); 769b50d902SRodney W. Grimes image = -1; 779b50d902SRodney W. Grimes /* 789b50d902SRodney W. Grimes * Now, determine how we are being used. 799b50d902SRodney W. Grimes * We successively pick off - flags. 809b50d902SRodney W. Grimes * If there is anything left, it is the base of the list 819b50d902SRodney W. Grimes * of users to mail to. Argp will be set to point to the 829b50d902SRodney W. Grimes * first of these users. 839b50d902SRodney W. Grimes */ 849ce73e90SMike Heffner ef = NULL; 859ce73e90SMike Heffner to = NULL; 869ce73e90SMike Heffner cc = NULL; 879ce73e90SMike Heffner bcc = NULL; 889ce73e90SMike Heffner smopts = NULL; 899ce73e90SMike Heffner subject = NULL; 90c92dfc23SMike Heffner while ((i = getopt(argc, argv, "FEHINT:b:c:edfins:u:v")) != -1) { 919b50d902SRodney W. Grimes switch (i) { 929b50d902SRodney W. Grimes case 'T': 939b50d902SRodney W. Grimes /* 949b50d902SRodney W. Grimes * Next argument is temp file to write which 959b50d902SRodney W. Grimes * articles have been read/deleted for netnews. 969b50d902SRodney W. Grimes */ 979b50d902SRodney W. Grimes Tflag = optarg; 980c3a8314SMike Heffner if ((i = open(Tflag, O_CREAT | O_TRUNC | O_WRONLY, 990c3a8314SMike Heffner 0600)) < 0) 1000c3a8314SMike Heffner err(1, "%s", Tflag); 1019ce73e90SMike Heffner (void)close(i); 1029b50d902SRodney W. Grimes break; 1039b50d902SRodney W. Grimes case 'u': 1049b50d902SRodney W. Grimes /* 1059b50d902SRodney W. Grimes * Next argument is person to pretend to be. 1069b50d902SRodney W. Grimes */ 1079b50d902SRodney W. Grimes myname = optarg; 10849936df3SJean-Marc Zucconi unsetenv("MAIL"); 1099b50d902SRodney W. Grimes break; 1109b50d902SRodney W. Grimes case 'i': 1119b50d902SRodney W. Grimes /* 1129b50d902SRodney W. Grimes * User wants to ignore interrupts. 1139b50d902SRodney W. Grimes * Set the variable "ignore" 1149b50d902SRodney W. Grimes */ 1159b50d902SRodney W. Grimes assign("ignore", ""); 1169b50d902SRodney W. Grimes break; 1179b50d902SRodney W. Grimes case 'd': 1189b50d902SRodney W. Grimes debug++; 1199b50d902SRodney W. Grimes break; 120c92dfc23SMike Heffner case 'e': 121c92dfc23SMike Heffner /* 122c92dfc23SMike Heffner * User wants to check mail and exit. 123c92dfc23SMike Heffner */ 124c92dfc23SMike Heffner assign("checkmode", ""); 125c92dfc23SMike Heffner break; 126c92dfc23SMike Heffner case 'H': 127c92dfc23SMike Heffner /* 128c92dfc23SMike Heffner * User wants a header summary only. 129c92dfc23SMike Heffner */ 130c92dfc23SMike Heffner assign("headersummary", ""); 131c92dfc23SMike Heffner break; 132c92dfc23SMike Heffner case 'F': 133c92dfc23SMike Heffner /* 134c92dfc23SMike Heffner * User wants to record messages to files 135c92dfc23SMike Heffner * named after first recipient username. 136c92dfc23SMike Heffner */ 137c92dfc23SMike Heffner assign("recordrecip", ""); 138c92dfc23SMike Heffner break; 1399b50d902SRodney W. Grimes case 's': 1409b50d902SRodney W. Grimes /* 1419b50d902SRodney W. Grimes * Give a subject field for sending from 1429b50d902SRodney W. Grimes * non terminal 1439b50d902SRodney W. Grimes */ 1449b50d902SRodney W. Grimes subject = optarg; 1459b50d902SRodney W. Grimes break; 1469b50d902SRodney W. Grimes case 'f': 1479b50d902SRodney W. Grimes /* 1489b50d902SRodney W. Grimes * User is specifying file to "edit" with Mail, 1499b50d902SRodney W. Grimes * as opposed to reading system mailbox. 1509b50d902SRodney W. Grimes * If no argument is given after -f, we read his 1519b50d902SRodney W. Grimes * mbox file. 1529b50d902SRodney W. Grimes * 1539b50d902SRodney W. Grimes * getopt() can't handle optional arguments, so here 1549b50d902SRodney W. Grimes * is an ugly hack to get around it. 1559b50d902SRodney W. Grimes */ 1569ce73e90SMike Heffner if ((argv[optind] != NULL) && (argv[optind][0] != '-')) 1579b50d902SRodney W. Grimes ef = argv[optind++]; 1589b50d902SRodney W. Grimes else 1599b50d902SRodney W. Grimes ef = "&"; 1609b50d902SRodney W. Grimes break; 1619b50d902SRodney W. Grimes case 'n': 1629b50d902SRodney W. Grimes /* 1639b50d902SRodney W. Grimes * User doesn't want to source /usr/lib/Mail.rc 1649b50d902SRodney W. Grimes */ 1659b50d902SRodney W. Grimes nosrc++; 1669b50d902SRodney W. Grimes break; 1679b50d902SRodney W. Grimes case 'N': 1689b50d902SRodney W. Grimes /* 1699b50d902SRodney W. Grimes * Avoid initial header printing. 1709b50d902SRodney W. Grimes */ 1719b50d902SRodney W. Grimes assign("noheader", ""); 1729b50d902SRodney W. Grimes break; 1739b50d902SRodney W. Grimes case 'v': 1749b50d902SRodney W. Grimes /* 1759b50d902SRodney W. Grimes * Send mailer verbose flag 1769b50d902SRodney W. Grimes */ 1779b50d902SRodney W. Grimes assign("verbose", ""); 1789b50d902SRodney W. Grimes break; 1799b50d902SRodney W. Grimes case 'I': 1809b50d902SRodney W. Grimes /* 1819b50d902SRodney W. Grimes * We're interactive 1829b50d902SRodney W. Grimes */ 1839b50d902SRodney W. Grimes assign("interactive", ""); 1849b50d902SRodney W. Grimes break; 1859b50d902SRodney W. Grimes case 'c': 1869b50d902SRodney W. Grimes /* 1879b50d902SRodney W. Grimes * Get Carbon Copy Recipient list 1889b50d902SRodney W. Grimes */ 1899b50d902SRodney W. Grimes cc = cat(cc, nalloc(optarg, GCC)); 1909b50d902SRodney W. Grimes break; 1919b50d902SRodney W. Grimes case 'b': 1929b50d902SRodney W. Grimes /* 1939b50d902SRodney W. Grimes * Get Blind Carbon Copy Recipient list 1949b50d902SRodney W. Grimes */ 1959b50d902SRodney W. Grimes bcc = cat(bcc, nalloc(optarg, GBCC)); 1969b50d902SRodney W. Grimes break; 197dcd24e27SMike Heffner case 'E': 198dcd24e27SMike Heffner /* 199dcd24e27SMike Heffner * Don't send empty files. 200dcd24e27SMike Heffner */ 201dcd24e27SMike Heffner assign("dontsendempty", ""); 202dcd24e27SMike Heffner break; 2039b50d902SRodney W. Grimes case '?': 2040c3a8314SMike Heffner fprintf(stderr, "\ 205e53e5e56SYaroslav Tykhiy Usage: %s [-dEiInv] [-s subject] [-c cc-addr] [-b bcc-addr] [-F] to-addr ...\n\ 206e53e5e56SYaroslav Tykhiy %*s [-sendmail-option ...]\n\ 207e53e5e56SYaroslav Tykhiy %s [-dEHiInNv] [-F] -f [name]\n\ 208e53e5e56SYaroslav Tykhiy %s [-dEHiInNv] [-F] [-u user]\n\ 209081aa516SDimitry Andric %s [-d] -e [-f name]\n", __progname, (int)strlen(__progname), "", 210e53e5e56SYaroslav Tykhiy __progname, __progname, __progname); 2119b50d902SRodney W. Grimes exit(1); 2129b50d902SRodney W. Grimes } 2139b50d902SRodney W. Grimes } 2149ce73e90SMike Heffner for (i = optind; (argv[i] != NULL) && (*argv[i] != '-'); i++) 2159b50d902SRodney W. Grimes to = cat(to, nalloc(argv[i], GTO)); 2169ce73e90SMike Heffner for (; argv[i] != NULL; i++) 2179b50d902SRodney W. Grimes smopts = cat(smopts, nalloc(argv[i], 0)); 2189b50d902SRodney W. Grimes /* 2199b50d902SRodney W. Grimes * Check for inconsistent arguments. 2209b50d902SRodney W. Grimes */ 2219ce73e90SMike Heffner if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL)) 2220c3a8314SMike Heffner errx(1, "You must specify direct recipients with -s, -c, or -b."); 2239ce73e90SMike Heffner if (ef != NULL && to != NULL) 2240c3a8314SMike Heffner errx(1, "Cannot give -f and people to send to."); 2259b50d902SRodney W. Grimes tinit(); 2269b50d902SRodney W. Grimes setscreensize(); 2279b50d902SRodney W. Grimes input = stdin; 2289b50d902SRodney W. Grimes rcvmode = !to; 2299b50d902SRodney W. Grimes spreserve(); 230e9b074c3SJordan K. Hubbard if (!nosrc) { 231e9b074c3SJordan K. Hubbard char *s, *path_rc; 232e9b074c3SJordan K. Hubbard 2330c3a8314SMike Heffner if ((path_rc = malloc(sizeof(_PATH_MASTER_RC))) == NULL) 2340c3a8314SMike Heffner err(1, "malloc(path_rc) failed"); 235e9b074c3SJordan K. Hubbard 236e9b074c3SJordan K. Hubbard strcpy(path_rc, _PATH_MASTER_RC); 237e9b074c3SJordan K. Hubbard while ((s = strsep(&path_rc, ":")) != NULL) 238e9b074c3SJordan K. Hubbard if (*s != '\0') 239e9b074c3SJordan K. Hubbard load(s); 240e9b074c3SJordan K. Hubbard } 2419b50d902SRodney W. Grimes /* 2429b50d902SRodney W. Grimes * Expand returns a savestr, but load only uses the file name 2439b50d902SRodney W. Grimes * for fopen, so it's safe to do this. 2449b50d902SRodney W. Grimes */ 245856f23edSMike Heffner if ((rc = getenv("MAILRC")) == NULL) 246856f23edSMike Heffner rc = "~/.mailrc"; 247856f23edSMike Heffner load(expand(rc)); 24859c3f4f7SMike Heffner 24959c3f4f7SMike Heffner replyto = value("REPLYTO"); 2509b50d902SRodney W. Grimes if (!rcvmode) { 25199bd6601SJoerg Wunsch mail(to, cc, bcc, smopts, subject, replyto); 2529b50d902SRodney W. Grimes /* 2539b50d902SRodney W. Grimes * why wait? 2549b50d902SRodney W. Grimes */ 2559b50d902SRodney W. Grimes exit(senderr); 2569b50d902SRodney W. Grimes } 257c92dfc23SMike Heffner 258c92dfc23SMike Heffner if(value("checkmode") != NULL) { 259c92dfc23SMike Heffner if (ef == NULL) 260c92dfc23SMike Heffner ef = "%"; 261c92dfc23SMike Heffner if (setfile(ef) <= 0) 262*389ae6c6SUlrich Spörlein /* Either an error has occurred, or no mail */ 263c92dfc23SMike Heffner exit(1); 264c92dfc23SMike Heffner else 265c92dfc23SMike Heffner exit(0); 266c92dfc23SMike Heffner /* NOTREACHED */ 267c92dfc23SMike Heffner } 268c92dfc23SMike Heffner 2699b50d902SRodney W. Grimes /* 2709b50d902SRodney W. Grimes * Ok, we are reading mail. 2719b50d902SRodney W. Grimes * Decide whether we are editing a mailbox or reading 2729b50d902SRodney W. Grimes * the system mailbox, and open up the right stuff. 2739b50d902SRodney W. Grimes */ 2749ce73e90SMike Heffner if (ef == NULL) 2759b50d902SRodney W. Grimes ef = "%"; 2769b50d902SRodney W. Grimes if (setfile(ef) < 0) 2779b50d902SRodney W. Grimes exit(1); /* error already reported */ 2789b50d902SRodney W. Grimes if (setjmp(hdrjmp) == 0) { 2799b50d902SRodney W. Grimes if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN) 2809ce73e90SMike Heffner (void)signal(SIGINT, hdrstop); 2819ce73e90SMike Heffner if (value("quiet") == NULL) 2829b50d902SRodney W. Grimes printf("Mail version %s. Type ? for help.\n", 2839b50d902SRodney W. Grimes version); 2849b50d902SRodney W. Grimes announce(); 2859ce73e90SMike Heffner (void)fflush(stdout); 2869ce73e90SMike Heffner (void)signal(SIGINT, prevint); 2879b50d902SRodney W. Grimes } 288c92dfc23SMike Heffner 289c92dfc23SMike Heffner /* If we were in header summary mode, it's time to exit. */ 290c92dfc23SMike Heffner if (value("headersummary") != NULL) 291c92dfc23SMike Heffner exit(0); 292c92dfc23SMike Heffner 2939b50d902SRodney W. Grimes commands(); 2949ce73e90SMike Heffner (void)signal(SIGHUP, SIG_IGN); 2959ce73e90SMike Heffner (void)signal(SIGINT, SIG_IGN); 2969ce73e90SMike Heffner (void)signal(SIGQUIT, SIG_IGN); 2979b50d902SRodney W. Grimes quit(); 2989b50d902SRodney W. Grimes exit(0); 2999b50d902SRodney W. Grimes } 3009b50d902SRodney W. Grimes 3019b50d902SRodney W. Grimes /* 3029b50d902SRodney W. Grimes * Interrupt printing of the headers. 3039b50d902SRodney W. Grimes */ 3049ce73e90SMike Heffner /*ARGSUSED*/ 3059b50d902SRodney W. Grimes void 3066d8484b0SPhilippe Charnier hdrstop(int signo __unused) 3079b50d902SRodney W. Grimes { 3089b50d902SRodney W. Grimes 3099ce73e90SMike Heffner (void)fflush(stdout); 3109b50d902SRodney W. Grimes fprintf(stderr, "\nInterrupt\n"); 3119b50d902SRodney W. Grimes longjmp(hdrjmp, 1); 3129b50d902SRodney W. Grimes } 3139b50d902SRodney W. Grimes 3149b50d902SRodney W. Grimes /* 3159b50d902SRodney W. Grimes * Compute what the screen size for printing headers should be. 3169b50d902SRodney W. Grimes * We use the following algorithm for the height: 3179b50d902SRodney W. Grimes * If baud rate < 1200, use 9 3189b50d902SRodney W. Grimes * If baud rate = 1200, use 14 3199b50d902SRodney W. Grimes * If baud rate > 1200, use 24 or ws_row 3209b50d902SRodney W. Grimes * Width is either 80 or ws_col; 3219b50d902SRodney W. Grimes */ 3229b50d902SRodney W. Grimes void 3236d8484b0SPhilippe Charnier setscreensize(void) 3249b50d902SRodney W. Grimes { 325856f23edSMike Heffner struct termios tbuf; 3269b50d902SRodney W. Grimes struct winsize ws; 327856f23edSMike Heffner speed_t speed; 3289b50d902SRodney W. Grimes 3299b50d902SRodney W. Grimes if (ioctl(1, TIOCGWINSZ, (char *)&ws) < 0) 3309b50d902SRodney W. Grimes ws.ws_col = ws.ws_row = 0; 331856f23edSMike Heffner if (tcgetattr(1, &tbuf) < 0) 3327c6d202aSPeter Wemm speed = B9600; 333856f23edSMike Heffner else 334856f23edSMike Heffner speed = cfgetospeed(&tbuf); 3357c6d202aSPeter Wemm if (speed < B1200) 3369b50d902SRodney W. Grimes screenheight = 9; 3377c6d202aSPeter Wemm else if (speed == B1200) 3389b50d902SRodney W. Grimes screenheight = 14; 3399b50d902SRodney W. Grimes else if (ws.ws_row != 0) 3409b50d902SRodney W. Grimes screenheight = ws.ws_row; 3419b50d902SRodney W. Grimes else 3429b50d902SRodney W. Grimes screenheight = 24; 3439b50d902SRodney W. Grimes if ((realscreenheight = ws.ws_row) == 0) 3449b50d902SRodney W. Grimes realscreenheight = 24; 3459b50d902SRodney W. Grimes if ((screenwidth = ws.ws_col) == 0) 3469b50d902SRodney W. Grimes screenwidth = 80; 3479b50d902SRodney W. Grimes } 348