1 /* $NetBSD: main.c,v 1.29 2008/07/21 14:19:24 lukem Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)main.c 8.2 (Berkeley) 4/20/95";
42 __RCSID("$NetBSD: main.c,v 1.29 2008/07/21 14:19:24 lukem Exp $");
67 * Mail -- a mail program
69 * Startup -- interface with user.
78 Usage: mail [-EiInv] [-r rcfile] [-s subject] [-a file] [-c cc-addr]\n\
79 [-b bcc-addr] to-addr ... [- sendmail-options ...]\n\
80 mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
81 mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
83 #else /* MIME_SUPPORT */
85 Usage: mail [-EiInv] [-r rcfile] [-s subject] [-c cc-addr] [-b bcc-addr]\n\
86 to-addr ... [- sendmail-options ...]\n\
87 mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
88 mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
90 #endif /* MIME_SUPPORT */
95 * Compute what the screen size for printing headers should be.
96 * We use the following algorithm for the height:
97 * If baud rate < 1200, use 9
98 * If baud rate = 1200, use 14
99 * If baud rate > 1200, use 24 or ws_row
100 * Width is either 80 or ws_col;
110 if (ioctl(1, TIOCGWINSZ
, &ws
) < 0)
111 ws
.ws_col
= ws
.ws_row
= 0;
112 if (tcgetattr(1, &tbuf
) < 0)
115 ospeed
= cfgetospeed(&tbuf
);
118 else if (ospeed
== 1200)
120 else if (ws
.ws_row
!= 0)
121 screenheight
= ws
.ws_row
;
124 if ((realscreenheight
= ws
.ws_row
) == 0)
125 realscreenheight
= 24;
126 if ((screenwidth
= ws
.ws_col
) == 0)
129 * Possible overrides from the rcfile.
131 if ((cp
= value(ENAME_SCREENWIDTH
)) != NULL
) {
133 width
= *cp
? atoi(cp
) : 0;
137 if ((cp
= value(ENAME_SCREENHEIGHT
)) != NULL
) {
139 height
= *cp
? atoi(cp
) : 0;
141 realscreenheight
= height
;
142 screenheight
= height
;
148 * Break up a white-space or comma delimited name list so that aliases
149 * can get expanded. Without this, the CC: or BCC: list is broken too
150 * late for alias expansion to occur.
153 lexpand(char *str
, int ntype
)
156 struct name
*np
= NULL
;
161 for (word
= list
; *word
; word
= p
) {
162 word
= skip_WSP(word
);
164 *p
&& !is_WSP(*p
) && *p
!= ',';
169 np
= cat(np
, nalloc(word
, ntype
));
177 main(int argc
, char *argv
[])
181 struct name
*to
, *cc
, *bcc
, *smopts
;
183 struct name
*attach_optargs
;
184 struct name
*attach_end
;
194 * For portability, call setprogname() early, before
195 * getprogname() is called.
197 (void)setprogname(argv
[0]);
200 * Set up a reasonable environment.
201 * Figure out whether we are being run interactively,
202 * start the SIGCHLD catcher, and so forth.
203 * (Other signals are setup later by sig_setup().)
205 (void)sigemptyset(&sa
.sa_mask
);
206 sa
.sa_flags
= SA_RESTART
;
207 sa
.sa_handler
= sigchild
;
208 (void)sigaction(SIGCHLD
, &sa
, NULL
);
211 assign(ENAME_INTERACTIVE
, "");
215 * Now, determine how we are being used.
216 * We successively pick off - flags.
217 * If there is anything left, it is the base of the list
218 * of users to mail to. Argp will be set to point to the
219 * first of these users.
230 attach_optargs
= NULL
;
232 while ((i
= getopt(argc
, argv
, ":~EH:INT:a:b:c:dfinr:s:u:v")) != -1)
234 while ((i
= getopt(argc
, argv
, ":~EH:INT:b:c:dfinr:s:u:v")) != -1)
240 * Next argument is temp file to write which
241 * articles have been read/deleted for netnews.
244 if ((i
= creat(Tflag
, 0600)) < 0) {
253 np
= nalloc(optarg
, 0);
254 if (attach_end
== NULL
)
257 np
->n_blink
= attach_end
;
258 attach_end
->n_flink
= np
;
266 * Next argument is person to pretend to be.
269 (void)unsetenv("MAIL");
273 * User wants to ignore interrupts.
274 * Set the variable "ignore"
276 assign(ENAME_IGNORE
, "");
286 * Give a subject field for sending from
293 * User is specifying file to "edit" with Mail,
294 * as opposed to reading system mailbox.
295 * If no argument is given after -f, we read his
298 * getopt() can't handle optional arguments, so here
299 * is an ugly hack to get around it.
301 if ((argv
[optind
]) && (argv
[optind
][0] != '-'))
308 * Print out the headers and quit.
310 Hflag
= get_Hflag(argv
);
314 * User doesn't want to source /usr/lib/Mail.rc
320 * Avoid initial header printing.
322 assign(ENAME_NOHEADER
, "");
326 * Send mailer verbose flag
328 assign(ENAME_VERBOSE
, "");
335 assign(ENAME_INTERACTIVE
, "");
339 * Get Carbon Copy Recipient list
341 cc
= cat(cc
, lexpand(optarg
, GCC
));
345 * Get Blind Carbon Copy Recipient list
347 bcc
= cat(bcc
, lexpand(optarg
, GBCC
));
352 * Don't send empty files.
354 assign(ENAME_DONTSENDEMPTY
, "");
358 * An optarg was expected but not found.
361 Hflag
= get_Hflag(NULL
);
364 (void)fprintf(stderr
,
365 "%s: option requires an argument -- %c\n",
366 getprogname(), optopt
);
371 * An unknown option flag. We need to do the
375 (void)fprintf(stderr
,
376 "%s: unknown option -- %c\n", getprogname(),
378 usage(); /* print usage message and die */
382 for (i
= optind
; (argv
[i
]) && (*argv
[i
] != '-'); i
++)
383 to
= cat(to
, nalloc(argv
[i
], GTO
));
384 for (/*EMPTY*/; argv
[i
]; i
++)
385 smopts
= cat(smopts
, nalloc(argv
[i
], GSMOPTS
));
387 * Check for inconsistent arguments.
389 if (to
== NULL
&& (subject
!= NULL
|| cc
!= NULL
|| bcc
!= NULL
))
390 errx(1, "You must specify direct recipients with -s, -c, or -b.");
391 if (ef
!= NULL
&& to
!= NULL
) {
392 errx(1, "Cannot give -f and people to send to.");
394 if (Hflag
!= 0 && to
!= NULL
)
395 errx(EXIT_FAILURE
, "Cannot give -H and people to send to.");
397 if (attach_optargs
!= NULL
&& to
== NULL
)
398 errx(EXIT_FAILURE
, "Cannot give -a without people to send to.");
400 tinit(); /* must be done before loading the rcfile */
402 mailmode
= Hflag
? mm_hdrsonly
:
403 to
? mm_sending
: mm_receiving
;
407 load(_PATH_MASTER_RC
);
409 * Expand returns a savestr, but load only uses the file name
410 * for fopen, so it's safe to do this.
412 if (rc
== NULL
&& (rc
= getenv("MAILRC")) == NULL
)
415 setscreensize(); /* do this after loading the rcfile */
419 * This is after loading the MAILRC so we can use value().
420 * Avoid editline in mm_hdrsonly mode or pipelines will screw
421 * up. XXX - there must be a better way!
423 if (mailmode
!= mm_hdrsonly
)
431 (void)mail(to
, cc
, bcc
, smopts
, subject
,
432 mime_attach_optargs(attach_optargs
));
437 break; /* XXX - keep lint happy */
442 * Ok, we are reading mail.
443 * Decide whether we are editing a mailbox or reading
444 * the system mailbox, and open up the right stuff.
449 exit(1); /* error already reported */
450 if (value(ENAME_QUIET
) == NULL
)
451 (void)printf("Mail version %s. Type ? for help.\n",
453 if (mailmode
== mm_hdrsonly
)
454 show_headers_and_exit(Hflag
); /* NORETURN */
456 (void)fflush(stdout
);
458 if (setjmp(jmpbuf
) != 0) {
459 /* Return here if quit() fails below. */
460 (void)printf("Use 'exit' to quit without saving changes.\n");
464 /* Ignore these signals from now on! */
465 (void)signal(SIGHUP
, SIG_IGN
);
466 (void)signal(SIGINT
, SIG_IGN
);
467 (void)signal(SIGQUIT
, SIG_IGN
);
472 assert(/*CONSTCOND*/0);