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