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 this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifdef notdef 14 char copyright[] = 15 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif /* notdef */ 18 19 #ifdef notdef 20 static char sccsid[] = "@(#)main.c 5.13 (Berkeley) 06/17/88"; 21 #endif /* notdef */ 22 23 #include "rcv.h" 24 #include <sys/stat.h> 25 26 /* 27 * Mail -- a mail program 28 * 29 * Startup -- interface with user. 30 */ 31 32 jmp_buf hdrjmp; 33 34 /* 35 * Find out who the user is, copy his mail file (if exists) into 36 * /tmp/Rxxxxx and set up the message pointers. Then, print out the 37 * message headers and read user commands. 38 * 39 * Command line syntax: 40 * Mail [ -i ] [ -r address ] [ -h number ] [ -f [ name ] ] 41 * or: 42 * Mail [ -i ] [ -r address ] [ -h number ] people ... 43 */ 44 45 main(argc, argv) 46 char **argv; 47 { 48 register char *ef, opt; 49 register int i; 50 struct name *to, *cc, *bcc, *smopts; 51 int mustsend, hdrstop(), (*prevint)(), f; 52 extern int getopt(), optind, opterr; 53 extern char *optarg; 54 55 /* 56 * Set up a reasonable environment. 57 * Figure out whether we are being run interactively, set up 58 * all the temporary files, buffer standard output, and so forth. 59 */ 60 mypid = getpid(); 61 if (isatty(0)) 62 assign("interactive", ""); 63 image = -1; 64 /* 65 * Now, determine how we are being used. 66 * We successively pick off instances of -r, -h, -f, and -i. 67 * If called as "rmail" we note this fact for letter sending. 68 * If there is anything left, it is the base of the list 69 * of users to mail to. Argp will be set to point to the 70 * first of these users. 71 */ 72 ef = NOSTR; 73 to = NULL; 74 cc = NULL; 75 bcc = NULL; 76 smopts = NULL; 77 mustsend = 0; 78 if (argc > 0 && **argv == 'r') 79 rmail++; 80 while ((opt = getopt(argc, argv, "INT:b:c:dfh:inr:s:u:v")) != EOF) { 81 switch (opt) { 82 case 'r': 83 /* 84 * Next argument is address to be sent along 85 * to the mailer. 86 */ 87 mustsend++; 88 rflag = optarg; 89 break; 90 case 'T': 91 /* 92 * Next argument is temp file to write which 93 * articles have been read/deleted for netnews. 94 */ 95 Tflag = optarg; 96 if ((f = creat(Tflag, 0600)) < 0) { 97 perror(Tflag); 98 exit(1); 99 } 100 close(f); 101 break; 102 case 'u': 103 /* 104 * Next argument is person to pretend to be. 105 */ 106 strcpy(myname, optarg); 107 break; 108 case 'i': 109 /* 110 * User wants to ignore interrupts. 111 * Set the variable "ignore" 112 */ 113 assign("ignore", ""); 114 break; 115 case 'd': 116 debug++; 117 break; 118 case 'h': 119 /* 120 * Specified sequence number for network. 121 * This is the number of "hops" made so 122 * far (count of times message has been 123 * forwarded) to help avoid infinite mail loops. 124 */ 125 mustsend++; 126 hflag = atoi(optarg); 127 if (hflag == 0) { 128 fprintf(stderr, "-h needs non-zero number\n"); 129 exit(1); 130 } 131 break; 132 case 's': 133 /* 134 * Give a subject field for sending from 135 * non terminal 136 */ 137 mustsend++; 138 sflag = optarg; 139 break; 140 case 'f': 141 /* 142 * User is specifying file to "edit" with Mail, 143 * as opposed to reading system mailbox. 144 * If no argument is given after -f, we read his 145 * mbox file. 146 * 147 * getopt() can't handle optional arguments, so here 148 * is an ugly hack to get around it. 149 */ 150 if ((argv[optind]) && (argv[optind][0] != '-')) 151 ef = argv[optind++]; 152 else 153 ef = "&"; 154 break; 155 case 'n': 156 /* 157 * User doesn't want to source /usr/lib/Mail.rc 158 */ 159 nosrc++; 160 break; 161 case 'N': 162 /* 163 * Avoid initial header printing. 164 */ 165 assign("noheader", ""); 166 break; 167 case 'v': 168 /* 169 * Send mailer verbose flag 170 */ 171 assign("verbose", ""); 172 break; 173 case 'I': 174 /* 175 * We're interactive 176 */ 177 assign("interactive", ""); 178 break; 179 case 'c': 180 /* 181 * Get Carbon Copy Recipient list 182 */ 183 cc = cat(cc, nalloc(optarg)); 184 mustsend++; 185 break; 186 case 'b': 187 /* 188 * Get Blind Carbon Copy Recipient list 189 */ 190 bcc = cat(bcc, nalloc(optarg)); 191 mustsend++; 192 break; 193 case '?': 194 fputs("\ 195 Usage: mail [-iInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\ 196 [- sendmail-options ...]\n\ 197 mail [-iInNv] -f [name]\n\ 198 mail [-iInNv] [-u user]\n", 199 stderr); 200 exit(1); 201 } 202 } 203 for (i = optind; (argv[i]) && (*argv[i] != '-'); i++) 204 to = cat(to, nalloc(argv[i])); 205 for (; argv[i]; i++) 206 smopts = cat(smopts, nalloc(argv[i])); 207 /* 208 * Check for inconsistent arguments. 209 */ 210 if (!to && (cc || bcc)) { 211 fputs("You must also specify direct recipients of mail.\n", stderr); 212 exit(1); 213 } 214 if ((ef != NOSTR) && to) { 215 fprintf(stderr, "Cannot give -f and people to send to.\n"); 216 exit(1); 217 } 218 if (mustsend && !to) { 219 fprintf(stderr, "The flags you gave make no sense since you're not sending mail.\n"); 220 exit(1); 221 } 222 tinit(); 223 setscreensize(); 224 input = stdin; 225 rcvmode = !to; 226 if (!nosrc) 227 load(MASTER); 228 load(mailrc); 229 if (!rcvmode) { 230 mail(to, cc, bcc, smopts); 231 232 /* 233 * why wait? 234 */ 235 236 exit(senderr); 237 } 238 239 /* 240 * Ok, we are reading mail. 241 * Decide whether we are editing a mailbox or reading 242 * the system mailbox, and open up the right stuff. 243 */ 244 if (ef != NOSTR) 245 edit++; 246 else 247 ef = "%"; 248 if ((ef = expand(ef)) == NOSTR) 249 exit(1); /* error already reported */ 250 if (setfile(ef, edit) < 0) { 251 if (edit) 252 perror(ef); 253 else 254 fprintf(stderr, "No mail for %s\n", myname); 255 exit(1); 256 } 257 if (setjmp(hdrjmp) == 0) { 258 extern char *version; 259 260 if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN) 261 signal(SIGINT, hdrstop); 262 if (value("quiet") == NOSTR) 263 printf("Mail version %s. Type ? for help.\n", 264 version); 265 announce(); 266 fflush(stdout); 267 signal(SIGINT, prevint); 268 } 269 if (!edit && msgCount == 0) { 270 printf("No mail\n"); 271 fflush(stdout); 272 exit(0); 273 } 274 commands(); 275 if (!edit) { 276 signal(SIGHUP, SIG_IGN); 277 signal(SIGINT, SIG_IGN); 278 signal(SIGQUIT, SIG_IGN); 279 quit(); 280 } 281 exit(0); 282 } 283 284 /* 285 * Interrupt printing of the headers. 286 */ 287 hdrstop() 288 { 289 290 fflush(stdout); 291 fprintf(stderr, "\nInterrupt\n"); 292 longjmp(hdrjmp, 1); 293 } 294 295 /* 296 * Compute what the screen size for printing headers should be. 297 * We use the following algorithm for the height: 298 * If baud rate < 1200, use 9 299 * If baud rate = 1200, use 14 300 * If baud rate > 1200, use 24 or ws_row 301 * Width is either 80 or ws_col; 302 */ 303 setscreensize() 304 { 305 struct sgttyb tbuf; 306 #ifdef TIOCGWINSZ 307 struct winsize ws; 308 309 if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0) 310 #endif 311 ws.ws_col = ws.ws_row = 0; 312 if (gtty(1, &tbuf) < 0) 313 tbuf.sg_ospeed = B9600; 314 if (tbuf.sg_ospeed < B1200) 315 screenheight = 9; 316 else if (tbuf.sg_ospeed == B1200) 317 screenheight = 14; 318 else if (ws.ws_row != 0) 319 screenheight = ws.ws_row; 320 else 321 screenheight = 24; 322 if ((realscreenheight = ws.ws_row) == 0) 323 realscreenheight = 24; 324 if ((screenwidth = ws.ws_col) == 0) 325 screenwidth = 80; 326 } 327