18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1980, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes /* 339b50d902SRodney W. Grimes * Mail -- a mail program 349b50d902SRodney W. Grimes * 359b50d902SRodney W. Grimes * Author: Kurt Shoens (UCB) March 25, 1978 369b50d902SRodney W. Grimes */ 379b50d902SRodney W. Grimes 389b50d902SRodney W. Grimes #include <sys/param.h> 399b50d902SRodney W. Grimes #include <sys/stat.h> 409b50d902SRodney W. Grimes 419b50d902SRodney W. Grimes #include <ctype.h> 420c3a8314SMike Heffner #include <err.h> 439ce73e90SMike Heffner #include <paths.h> 449ce73e90SMike Heffner #include <signal.h> 459ce73e90SMike Heffner #include <stdio.h> 469ce73e90SMike Heffner #include <stdlib.h> 479b50d902SRodney W. Grimes #include <string.h> 489ce73e90SMike Heffner #include <termios.h> 499ce73e90SMike Heffner #include <time.h> 509ce73e90SMike Heffner #include <unistd.h> 519ce73e90SMike Heffner 529b50d902SRodney W. Grimes #include "pathnames.h" 539b50d902SRodney W. Grimes 549b50d902SRodney W. Grimes #define APPEND /* New mail goes to end of mailbox */ 559b50d902SRodney W. Grimes 569b50d902SRodney W. Grimes #define ESCAPE '~' /* Default escape for sending */ 579b50d902SRodney W. Grimes #define NMLSIZE 1024 /* max names in a message list */ 589b50d902SRodney W. Grimes #define PATHSIZE MAXPATHLEN /* Size of pathnames throughout */ 599b50d902SRodney W. Grimes #define HSHSIZE 59 /* Hash size for aliases and vars */ 609b50d902SRodney W. Grimes #define LINESIZE BUFSIZ /* max readable line width */ 619b50d902SRodney W. Grimes #define STRINGSIZE ((unsigned)128) /* Dynamic allocation units */ 629b50d902SRodney W. Grimes #define MAXARGC 1024 /* Maximum list of raw strings */ 639b50d902SRodney W. Grimes #define MAXEXP 25 /* Maximum expansion of aliases */ 649b50d902SRodney W. Grimes 659b50d902SRodney W. Grimes #define equal(a, b) (strcmp(a,b)==0)/* A nice function to string compare */ 669b50d902SRodney W. Grimes 679b50d902SRodney W. Grimes struct message { 689b50d902SRodney W. Grimes short m_flag; /* flags, see below */ 699b50d902SRodney W. Grimes short m_offset; /* offset in block of message */ 70f14d551cSAndrey A. Chernov long m_block; /* block number of this message */ 719b50d902SRodney W. Grimes long m_size; /* Bytes in the message */ 72f14d551cSAndrey A. Chernov long m_lines; /* Lines in the message */ 739b50d902SRodney W. Grimes }; 749b50d902SRodney W. Grimes 759b50d902SRodney W. Grimes /* 769b50d902SRodney W. Grimes * flag bits. 779b50d902SRodney W. Grimes */ 789b50d902SRodney W. Grimes 799b50d902SRodney W. Grimes #define MUSED (1<<0) /* entry is used, but this bit isn't */ 809b50d902SRodney W. Grimes #define MDELETED (1<<1) /* entry has been deleted */ 819b50d902SRodney W. Grimes #define MSAVED (1<<2) /* entry has been saved */ 829b50d902SRodney W. Grimes #define MTOUCH (1<<3) /* entry has been noticed */ 839b50d902SRodney W. Grimes #define MPRESERVE (1<<4) /* keep entry in sys mailbox */ 849b50d902SRodney W. Grimes #define MMARK (1<<5) /* message is marked! */ 859b50d902SRodney W. Grimes #define MODIFY (1<<6) /* message has been modified */ 869b50d902SRodney W. Grimes #define MNEW (1<<7) /* message has never been seen */ 879b50d902SRodney W. Grimes #define MREAD (1<<8) /* message has been read sometime. */ 889b50d902SRodney W. Grimes #define MSTATUS (1<<9) /* message status has changed */ 899b50d902SRodney W. Grimes #define MBOX (1<<10) /* Send this to mbox, regardless */ 909b50d902SRodney W. Grimes 919b50d902SRodney W. Grimes /* 929b50d902SRodney W. Grimes * Given a file address, determine the block number it represents. 939b50d902SRodney W. Grimes */ 949b50d902SRodney W. Grimes #define blockof(off) ((int)((off) / 4096)) 95c23d986eSPoul-Henning Kamp #define boffsetof(off) ((int)((off) % 4096)) 969b50d902SRodney W. Grimes #define positionof(block, offset) ((off_t)(block) * 4096 + (offset)) 979b50d902SRodney W. Grimes 989b50d902SRodney W. Grimes /* 999b50d902SRodney W. Grimes * Format of the command description table. 1009b50d902SRodney W. Grimes * The actual table is declared and initialized 1019b50d902SRodney W. Grimes * in lex.c 1029b50d902SRodney W. Grimes */ 1039b50d902SRodney W. Grimes struct cmd { 1049ce73e90SMike Heffner const char *c_name; /* Name of command */ 105*d28a9551SJohn Baldwin int (*c_func)(void *); /* Implementor of the command */ 1069b50d902SRodney W. Grimes short c_argtype; /* Type of arglist (see below) */ 1079b50d902SRodney W. Grimes short c_msgflag; /* Required flags of messages */ 1089b50d902SRodney W. Grimes short c_msgmask; /* Relevant flags of messages */ 1099b50d902SRodney W. Grimes }; 1109b50d902SRodney W. Grimes 1119b50d902SRodney W. Grimes /* Yechh, can't initialize unions */ 1129b50d902SRodney W. Grimes 1139b50d902SRodney W. Grimes #define c_minargs c_msgflag /* Minimum argcount for RAWLIST */ 1149b50d902SRodney W. Grimes #define c_maxargs c_msgmask /* Max argcount for RAWLIST */ 1159b50d902SRodney W. Grimes 1169b50d902SRodney W. Grimes /* 1179b50d902SRodney W. Grimes * Argument types. 1189b50d902SRodney W. Grimes */ 1199b50d902SRodney W. Grimes 1209b50d902SRodney W. Grimes #define MSGLIST 0 /* Message list type */ 1219b50d902SRodney W. Grimes #define STRLIST 1 /* A pure string */ 1229b50d902SRodney W. Grimes #define RAWLIST 2 /* Shell string list */ 1239b50d902SRodney W. Grimes #define NOLIST 3 /* Just plain 0 */ 1249b50d902SRodney W. Grimes #define NDMLIST 4 /* Message list, no defaults */ 1259b50d902SRodney W. Grimes 1269b50d902SRodney W. Grimes #define P 040 /* Autoprint dot after command */ 1279b50d902SRodney W. Grimes #define I 0100 /* Interactive command bit */ 1289b50d902SRodney W. Grimes #define M 0200 /* Legal from send mode bit */ 1299b50d902SRodney W. Grimes #define W 0400 /* Illegal when read only bit */ 1309b50d902SRodney W. Grimes #define F 01000 /* Is a conditional command */ 1319b50d902SRodney W. Grimes #define T 02000 /* Is a transparent command */ 1329b50d902SRodney W. Grimes #define R 04000 /* Cannot be called from collect */ 1339b50d902SRodney W. Grimes 1349b50d902SRodney W. Grimes /* 1359b50d902SRodney W. Grimes * Oft-used mask values 1369b50d902SRodney W. Grimes */ 1379b50d902SRodney W. Grimes 1389b50d902SRodney W. Grimes #define MMNORM (MDELETED|MSAVED)/* Look at both save and delete bits */ 1399b50d902SRodney W. Grimes #define MMNDEL MDELETED /* Look only at deleted bit */ 1409b50d902SRodney W. Grimes 1419b50d902SRodney W. Grimes /* 1429b50d902SRodney W. Grimes * Structure used to return a break down of a head 1439b50d902SRodney W. Grimes * line (hats off to Bill Joy!) 1449b50d902SRodney W. Grimes */ 1459b50d902SRodney W. Grimes 1469b50d902SRodney W. Grimes struct headline { 1479b50d902SRodney W. Grimes char *l_from; /* The name of the sender */ 1489b50d902SRodney W. Grimes char *l_tty; /* His tty string (if any) */ 1499b50d902SRodney W. Grimes char *l_date; /* The entire date string */ 1509b50d902SRodney W. Grimes }; 1519b50d902SRodney W. Grimes 1529b50d902SRodney W. Grimes #define GTO 1 /* Grab To: line */ 1539b50d902SRodney W. Grimes #define GSUBJECT 2 /* Likewise, Subject: line */ 1549b50d902SRodney W. Grimes #define GCC 4 /* And the Cc: line */ 1559b50d902SRodney W. Grimes #define GBCC 8 /* And also the Bcc: line */ 15699bd6601SJoerg Wunsch #define GREPLYTO 0x10 /* And the Reply-To: line */ 15799bd6601SJoerg Wunsch #define GINREPLYTO 0x20 /* The In-Reply-To: line */ 15899bd6601SJoerg Wunsch #define GMASK (GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO) 1599b50d902SRodney W. Grimes /* Mask of places from whence */ 1609b50d902SRodney W. Grimes 16199bd6601SJoerg Wunsch #define GNL 0x40 /* Print blank line after */ 16299bd6601SJoerg Wunsch #define GDEL 0x80 /* Entity removed from list */ 16399bd6601SJoerg Wunsch #define GCOMMA 0x100 /* detract puts in commas */ 1649b50d902SRodney W. Grimes 1659b50d902SRodney W. Grimes /* 1669b50d902SRodney W. Grimes * Structure used to pass about the current 1679b50d902SRodney W. Grimes * state of the user-typed message header. 1689b50d902SRodney W. Grimes */ 1699b50d902SRodney W. Grimes 1709b50d902SRodney W. Grimes struct header { 1719b50d902SRodney W. Grimes struct name *h_bcc; /* Blind carbon copies */ 1729ce73e90SMike Heffner struct name *h_cc; /* Carbon copies string */ 1739b50d902SRodney W. Grimes struct name *h_smopts; /* Sendmail options */ 1749ce73e90SMike Heffner struct name *h_to; /* Dynamic "To:" string */ 1759ce73e90SMike Heffner char *h_inreplyto; /* Reference */ 1769ce73e90SMike Heffner char *h_replyto; /* Reply address */ 1779ce73e90SMike Heffner char *h_subject; /* Subject string */ 1789b50d902SRodney W. Grimes }; 1799b50d902SRodney W. Grimes 1809b50d902SRodney W. Grimes /* 1819b50d902SRodney W. Grimes * Structure of namelist nodes used in processing 1829b50d902SRodney W. Grimes * the recipients of mail and aliases and all that 1839b50d902SRodney W. Grimes * kind of stuff. 1849b50d902SRodney W. Grimes */ 1859b50d902SRodney W. Grimes 1869b50d902SRodney W. Grimes struct name { 1879b50d902SRodney W. Grimes struct name *n_flink; /* Forward link in list. */ 1889b50d902SRodney W. Grimes struct name *n_blink; /* Backward list link */ 1899b50d902SRodney W. Grimes short n_type; /* From which list it came */ 1909b50d902SRodney W. Grimes char *n_name; /* This fella's name */ 1919b50d902SRodney W. Grimes }; 1929b50d902SRodney W. Grimes 1939b50d902SRodney W. Grimes /* 1949b50d902SRodney W. Grimes * Structure of a variable node. All variables are 1959b50d902SRodney W. Grimes * kept on a singly-linked list of these, rooted by 1969b50d902SRodney W. Grimes * "variables" 1979b50d902SRodney W. Grimes */ 1989b50d902SRodney W. Grimes 1999b50d902SRodney W. Grimes struct var { 2009b50d902SRodney W. Grimes struct var *v_link; /* Forward link to next variable */ 2019b50d902SRodney W. Grimes char *v_name; /* The variable's name */ 2029b50d902SRodney W. Grimes char *v_value; /* And it's current value */ 2039b50d902SRodney W. Grimes }; 2049b50d902SRodney W. Grimes 2059b50d902SRodney W. Grimes struct group { 2069b50d902SRodney W. Grimes struct group *ge_link; /* Next person in this group */ 2079b50d902SRodney W. Grimes char *ge_name; /* This person's user name */ 2089b50d902SRodney W. Grimes }; 2099b50d902SRodney W. Grimes 2109b50d902SRodney W. Grimes struct grouphead { 2119b50d902SRodney W. Grimes struct grouphead *g_link; /* Next grouphead in list */ 2129b50d902SRodney W. Grimes char *g_name; /* Name of this group */ 2139b50d902SRodney W. Grimes struct group *g_list; /* Users in group. */ 2149b50d902SRodney W. Grimes }; 2159b50d902SRodney W. Grimes 2169b50d902SRodney W. Grimes /* 2179b50d902SRodney W. Grimes * Structure of the hash table of ignored header fields 2189b50d902SRodney W. Grimes */ 2199b50d902SRodney W. Grimes struct ignoretab { 2209b50d902SRodney W. Grimes int i_count; /* Number of entries */ 2219b50d902SRodney W. Grimes struct ignore { 2229b50d902SRodney W. Grimes struct ignore *i_link; /* Next ignored field in bucket */ 2239b50d902SRodney W. Grimes char *i_field; /* This ignored field */ 2249b50d902SRodney W. Grimes } *i_head[HSHSIZE]; 2259b50d902SRodney W. Grimes }; 2269b50d902SRodney W. Grimes 2279b50d902SRodney W. Grimes /* 2289b50d902SRodney W. Grimes * Token values returned by the scanner used for argument lists. 2299b50d902SRodney W. Grimes * Also, sizes of scanner-related things. 2309b50d902SRodney W. Grimes */ 2319b50d902SRodney W. Grimes 2329b50d902SRodney W. Grimes #define TEOL 0 /* End of the command line */ 2339b50d902SRodney W. Grimes #define TNUMBER 1 /* A message number */ 2349b50d902SRodney W. Grimes #define TDASH 2 /* A simple dash */ 2359b50d902SRodney W. Grimes #define TSTRING 3 /* A string (possibly containing -) */ 2369b50d902SRodney W. Grimes #define TDOT 4 /* A "." */ 2379b50d902SRodney W. Grimes #define TUP 5 /* An "^" */ 2389b50d902SRodney W. Grimes #define TDOLLAR 6 /* A "$" */ 2399b50d902SRodney W. Grimes #define TSTAR 7 /* A "*" */ 2409b50d902SRodney W. Grimes #define TOPEN 8 /* An '(' */ 2419b50d902SRodney W. Grimes #define TCLOSE 9 /* A ')' */ 2429b50d902SRodney W. Grimes #define TPLUS 10 /* A '+' */ 2439b50d902SRodney W. Grimes #define TERROR 11 /* A lexical error */ 2449b50d902SRodney W. Grimes 2459b50d902SRodney W. Grimes #define REGDEP 2 /* Maximum regret depth. */ 2469b50d902SRodney W. Grimes #define STRINGLEN 1024 /* Maximum length of string token */ 2479b50d902SRodney W. Grimes 2489b50d902SRodney W. Grimes /* 2499b50d902SRodney W. Grimes * Constants for conditional commands. These describe whether 2509b50d902SRodney W. Grimes * we should be executing stuff or not. 2519b50d902SRodney W. Grimes */ 2529b50d902SRodney W. Grimes 2539b50d902SRodney W. Grimes #define CANY 0 /* Execute in send or receive mode */ 2549b50d902SRodney W. Grimes #define CRCV 1 /* Execute in receive mode only */ 2559b50d902SRodney W. Grimes #define CSEND 2 /* Execute in send mode only */ 2569b50d902SRodney W. Grimes 2579b50d902SRodney W. Grimes /* 2589b50d902SRodney W. Grimes * Kludges to handle the change from setexit / reset to setjmp / longjmp 2599b50d902SRodney W. Grimes */ 2609b50d902SRodney W. Grimes 2619b50d902SRodney W. Grimes #define setexit() setjmp(srbuf) 2629b50d902SRodney W. Grimes #define reset(x) longjmp(srbuf, x) 2639b50d902SRodney W. Grimes 2649b50d902SRodney W. Grimes /* 2659b50d902SRodney W. Grimes * Truncate a file to the last character written. This is 2669b50d902SRodney W. Grimes * useful just before closing an old file that was opened 2679b50d902SRodney W. Grimes * for read/write. 2689b50d902SRodney W. Grimes */ 2699b50d902SRodney W. Grimes #define trunc(stream) { \ 2709b50d902SRodney W. Grimes (void)fflush(stream); \ 2710bfdca97SPedro F. Giffuni (void)ftruncate(fileno(stream), ftello(stream)); \ 2729b50d902SRodney W. Grimes } 273