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