1 /* 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1980, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 04/20/95"; 16 #endif /* not lint */ 17 18 #include "rcv.h" 19 #include <fcntl.h> 20 #include "extern.h" 21 22 /* 23 * Mail -- a mail program 24 * 25 * Startup -- interface with user. 26 */ 27 28 jmp_buf hdrjmp; 29 30 int 31 main(argc, argv) 32 int argc; 33 char *argv[]; 34 { 35 register int i; 36 struct name *to, *cc, *bcc, *smopts; 37 char *subject; 38 char *ef; 39 char nosrc = 0; 40 void hdrstop(); 41 sig_t prevint; 42 void sigchild(); 43 char *rc; 44 45 /* 46 * Set up a reasonable environment. 47 * Figure out whether we are being run interactively, 48 * start the SIGCHLD catcher, and so forth. 49 */ 50 (void) signal(SIGCHLD, sigchild); 51 if (isatty(0)) 52 assign("interactive", ""); 53 image = -1; 54 /* 55 * Now, determine how we are being used. 56 * We successively pick off - flags. 57 * If there is anything left, it is the base of the list 58 * of users to mail to. Argp will be set to point to the 59 * first of these users. 60 */ 61 ef = NOSTR; 62 to = NIL; 63 cc = NIL; 64 bcc = NIL; 65 smopts = NIL; 66 subject = NOSTR; 67 while ((i = getopt(argc, argv, "INT:b:c:dfins:u:v")) != EOF) { 68 switch (i) { 69 case 'T': 70 /* 71 * Next argument is temp file to write which 72 * articles have been read/deleted for netnews. 73 */ 74 Tflag = optarg; 75 if ((i = creat(Tflag, 0600)) < 0) { 76 perror(Tflag); 77 exit(1); 78 } 79 close(i); 80 break; 81 case 'u': 82 /* 83 * Next argument is person to pretend to be. 84 */ 85 myname = optarg; 86 break; 87 case 'i': 88 /* 89 * User wants to ignore interrupts. 90 * Set the variable "ignore" 91 */ 92 assign("ignore", ""); 93 break; 94 case 'd': 95 debug++; 96 break; 97 case 's': 98 /* 99 * Give a subject field for sending from 100 * non terminal 101 */ 102 subject = optarg; 103 break; 104 case 'f': 105 /* 106 * User is specifying file to "edit" with Mail, 107 * as opposed to reading system mailbox. 108 * If no argument is given after -f, we read his 109 * mbox file. 110 * 111 * getopt() can't handle optional arguments, so here 112 * is an ugly hack to get around it. 113 */ 114 if ((argv[optind]) && (argv[optind][0] != '-')) 115 ef = argv[optind++]; 116 else 117 ef = "&"; 118 break; 119 case 'n': 120 /* 121 * User doesn't want to source /usr/lib/Mail.rc 122 */ 123 nosrc++; 124 break; 125 case 'N': 126 /* 127 * Avoid initial header printing. 128 */ 129 assign("noheader", ""); 130 break; 131 case 'v': 132 /* 133 * Send mailer verbose flag 134 */ 135 assign("verbose", ""); 136 break; 137 case 'I': 138 /* 139 * We're interactive 140 */ 141 assign("interactive", ""); 142 break; 143 case 'c': 144 /* 145 * Get Carbon Copy Recipient list 146 */ 147 cc = cat(cc, nalloc(optarg, GCC)); 148 break; 149 case 'b': 150 /* 151 * Get Blind Carbon Copy Recipient list 152 */ 153 bcc = cat(bcc, nalloc(optarg, GBCC)); 154 break; 155 case '?': 156 fputs("\ 157 Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\ 158 [- sendmail-options ...]\n\ 159 mail [-iInNv] -f [name]\n\ 160 mail [-iInNv] [-u user]\n", 161 stderr); 162 exit(1); 163 } 164 } 165 for (i = optind; (argv[i]) && (*argv[i] != '-'); i++) 166 to = cat(to, nalloc(argv[i], GTO)); 167 for (; argv[i]; i++) 168 smopts = cat(smopts, nalloc(argv[i], 0)); 169 /* 170 * Check for inconsistent arguments. 171 */ 172 if (to == NIL && (subject != NOSTR || cc != NIL || bcc != NIL)) { 173 fputs("You must specify direct recipients with -s, -c, or -b.\n", stderr); 174 exit(1); 175 } 176 if (ef != NOSTR && to != NIL) { 177 fprintf(stderr, "Cannot give -f and people to send to.\n"); 178 exit(1); 179 } 180 tinit(); 181 setscreensize(); 182 input = stdin; 183 rcvmode = !to; 184 spreserve(); 185 if (!nosrc) 186 load(_PATH_MASTER_RC); 187 /* 188 * Expand returns a savestr, but load only uses the file name 189 * for fopen, so it's safe to do this. 190 */ 191 if ((rc = getenv("MAILRC")) == 0) 192 rc = "~/.mailrc"; 193 load(expand(rc)); 194 if (!rcvmode) { 195 mail(to, cc, bcc, smopts, subject); 196 /* 197 * why wait? 198 */ 199 exit(senderr); 200 } 201 /* 202 * Ok, we are reading mail. 203 * Decide whether we are editing a mailbox or reading 204 * the system mailbox, and open up the right stuff. 205 */ 206 if (ef == NOSTR) 207 ef = "%"; 208 if (setfile(ef) < 0) 209 exit(1); /* error already reported */ 210 if (setjmp(hdrjmp) == 0) { 211 extern char *version; 212 213 if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN) 214 signal(SIGINT, hdrstop); 215 if (value("quiet") == NOSTR) 216 printf("Mail version %s. Type ? for help.\n", 217 version); 218 announce(); 219 fflush(stdout); 220 signal(SIGINT, prevint); 221 } 222 commands(); 223 signal(SIGHUP, SIG_IGN); 224 signal(SIGINT, SIG_IGN); 225 signal(SIGQUIT, SIG_IGN); 226 quit(); 227 exit(0); 228 } 229 230 /* 231 * Interrupt printing of the headers. 232 */ 233 void 234 hdrstop(signo) 235 int signo; 236 { 237 238 fflush(stdout); 239 fprintf(stderr, "\nInterrupt\n"); 240 longjmp(hdrjmp, 1); 241 } 242 243 /* 244 * Compute what the screen size for printing headers should be. 245 * We use the following algorithm for the height: 246 * If baud rate < 1200, use 9 247 * If baud rate = 1200, use 14 248 * If baud rate > 1200, use 24 or ws_row 249 * Width is either 80 or ws_col; 250 */ 251 void 252 setscreensize() 253 { 254 struct termios tbuf; 255 struct winsize ws; 256 int ospeed; 257 258 if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0) 259 ws.ws_col = ws.ws_row = 0; 260 if (ioctl(1, TIOCGETA, &tbuf) < 0) 261 ospeed = B9600; 262 else 263 ospeed = cfgetospeed(&tbuf); 264 if (ospeed < B1200) 265 screenheight = 9; 266 else if (ospeed == B1200) 267 screenheight = 14; 268 else if (ws.ws_row != 0) 269 screenheight = ws.ws_row; 270 else 271 screenheight = 24; 272 if ((realscreenheight = ws.ws_row) == 0) 273 realscreenheight = 24; 274 if ((screenwidth = ws.ws_col) == 0) 275 screenwidth = 80; 276 } 277