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