From Anon Ymous:

- Remove all longjmp(3) calls from signal handlers.  Instead, we post
to an internal signal queue and check that periodically.  All signal
related code is now in sig.c, except for the SIGCHLD handler which
remains in popen.c as it is intimately tied to routines there.

- Handle SIGPIPE in type1() regardless of mime support, or else the
handler in execute() will prevent our error code from being returned
resulting in 'sawcom' not being set on the first command as it should.
This only affected the initial behavior of the "next" command without
mime support.

- Add the 'T' flag to many commands in cmdtab.c that should not look
like the first command.  E.g., start mail on a mailbox with multiple
messages, run "set foo", then "next", and watch the second message get
displayed rather than the first as is the case without the first "set"
command.

- Add file descriptor and file handle leak detection.  Enabled by
DEBUG_FILE_LEAK.  This will likely disappear in the future.

- Fix a long standing (since import in 1993) longjmp() bug in
edstop(): the jmpbuf was invalid when quit() is called at the end of
main.

- Fix a long standing bug (since import in 1993) in snarf() where it
didn't strip whitespace correctly if the line consisted only of
whitespace.

- Lint cleanup.

- New Feature: "Header" command.  This allows miscellaneous header
fields to be added to the header, e.g., "X-Organization:" or
"Reply-To:" fields.

- New Feature: "page-also" variable.  This allows the specification of
additional commands to page.  It is more flexible than "crt".

- Document the "pager-off" variable: if set, it disables paging
entirely.
This commit is contained in:
christos 2009-04-10 13:08:24 +00:00
parent 889c434e54
commit ca13337dfe
35 changed files with 1889 additions and 866 deletions

View File

@ -1,20 +1,30 @@
# $NetBSD: Makefile,v 1.30 2007/05/28 12:06:28 tls Exp $
# $NetBSD: Makefile,v 1.31 2009/04/10 13:08:24 christos Exp $
# @(#)Makefile 8.3 (Berkeley) 4/20/95
.include <bsd.own.mk>
USE_FORT?= yes # data-driven bugs?
USE_EDITLINE=yes
MIME_SUPPORT=yes # currently requires USE_EDITLINE
CHARSET_SUPPORT=yes # requires MIME_SUPPORT
THREAD_SUPPORT=yes # EXPERIMENTAL
USE_EDITLINE?=yes
MIME_SUPPORT?=yes # currently requires USE_EDITLINE
CHARSET_SUPPORT?=yes # requires MIME_SUPPORT
THREAD_SUPPORT?=yes # EXPERIMENTAL
# Work around some problems in -current.
# See the source code for more info.
#
CPPFLAGS+= -DBROKEN_EXEC_TTY_RESTORE # broken since 4.99.10
CPPFLAGS+= -DBROKEN_CLONE_STAT # see PRs 37878 and 37550
# Debugging options (most should go away - please leave for now).
#
#CPPFLAGS+= -DDEBUG_FILE_LEAK
PROG= mail
SRCS= version.c support.c cmd1.c cmd2.c cmd3.c cmd4.c cmdtab.c collect.c \
dotlock.c edit.c fio.c format.c getname.c head.c v7.local.c lex.c \
list.c main.c names.c popen.c quit.c send.c strings.c temp.c tty.c \
vars.c
list.c main.c names.c popen.c quit.c send.c sig.c strings.c temp.c \
tty.c vars.c
LINKS= ${BINDIR}/mail ${BINDIR}/Mail ${BINDIR}/mail ${BINDIR}/mailx
MLINKS= mail.1 Mail.1 mail.1 mailx.1

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmd1.c,v 1.29 2007/10/29 23:20:37 christos Exp $ */
/* $NetBSD: cmd1.c,v 1.30 2009/04/10 13:08:24 christos Exp $ */
/*-
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)cmd1.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: cmd1.c,v 1.29 2007/10/29 23:20:37 christos Exp $");
__RCSID("$NetBSD: cmd1.c,v 1.30 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
@ -46,6 +46,7 @@ __RCSID("$NetBSD: cmd1.c,v 1.29 2007/10/29 23:20:37 christos Exp $");
#ifdef MIME_SUPPORT
#include "mime.h"
#endif
#include "sig.h"
#include "thread.h"
@ -88,6 +89,7 @@ printhead(int mesg)
if (screenwidth > 0)
msgline[screenwidth] = '\0';
(void)printf("%s\n", msgline);
sig_check();
}
/*
@ -97,11 +99,13 @@ printhead(int mesg)
PUBLIC int
headers(void *v)
{
int *msgvec = v;
int n, flag;
int *msgvec;
int n;
int flag;
struct message *mp;
int size;
msgvec = v;
size = screensize();
n = msgvec[0];
if (n != 0)
@ -140,10 +144,12 @@ headers(void *v)
PUBLIC int
scroll(void *v)
{
char *arg = v;
int s, size;
char *arg;
int s;
int size;
int cur[1];
arg = v;
cur[0] = 0;
size = screensize();
s = screen;
@ -180,9 +186,10 @@ scroll(void *v)
PUBLIC int
from(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
msgvec = v;
for (ip = msgvec; *ip != 0; ip++)
printhead(*ip);
if (--ip >= msgvec)
@ -214,10 +221,11 @@ PUBLIC int
pcmdlist(void *v __unused)
{
const struct cmd *cp;
int cc;
size_t cc;
(void)printf("Commands are:\n");
for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
cc = 0;
for (cp = cmdtab; cp->c_name != NULL; cp++) {
cc += strlen(cp->c_name) + 2;
if (cc > 72) {
(void)printf("\n");
@ -227,6 +235,7 @@ pcmdlist(void *v __unused)
(void)printf("%s, ", cp->c_name);
else
(void)printf("%s\n", cp->c_name);
sig_check();
}
return 0;
}
@ -236,6 +245,7 @@ PUBLIC char *
sget_msgnum(struct message *mp, struct message *parent)
{
char *p;
if (parent == NULL || parent == mp) {
(void)sasprintf(&p, "%d", mp->m_index);
return p;
@ -249,6 +259,7 @@ sget_msgnum(struct message *mp, struct message *parent)
PUBLIC void
show_msgnum(FILE *obuf, struct message *mp, struct message *parent)
{
if (value(ENAME_QUIET) == NULL)
(void)fprintf(obuf, "Message %s:\n", sget_msgnum(mp, parent));
}
@ -278,6 +289,7 @@ type1_core(struct message *mp, void *v)
#else
(void)sendmessage(mp, args->obuf, args->igtab, NULL, NULL);
#endif
sig_check();
return 0;
}
@ -289,8 +301,9 @@ static jmp_buf pipestop;
/*ARGSUSED*/
static void
brokpipe(int signo __unused)
cmd1_brokpipe(int signo __unused)
{
longjmp(pipestop, 1);
}
@ -311,25 +324,27 @@ type1(int *msgvec, int doign, int mime_decode)
* starting values. Note it is the variable that is volatile,
* not what it is pointing at!
*/
FILE *volatile obuf; /* avoid longjmp clobbering? */
FILE *volatile obuf; /* avoid longjmp clobbering */
sig_t volatile oldsigpipe; /* avoid longjmp clobbering? */
#ifdef MIME_SUPPORT
sig_t volatile oldsigpipe; /* XXX - is volatile needed? */
struct mime_info *volatile mip; /* avoid longjmp clobbering - needed */
struct mime_info *volatile mip; /* avoid longjmp clobbering? */
mip = NULL;
#endif
if ((obuf = last_registered_file(0)) == NULL)
obuf = stdout;
#ifdef MIME_SUPPORT
mip = NULL;
oldsigpipe = signal(SIGPIPE, SIG_IGN);
/*
* Even without MIME_SUPPORT, we need to handle SIGPIPE here
* or else the handler in execute() will grab things and our
* exit code will never be seen.
*/
sig_check();
oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
if (setjmp(pipestop))
goto close_pipe;
(void)signal(SIGPIPE, brokpipe);
#endif
msgCount = get_msgCount();
recursive = do_recursion();
@ -349,17 +364,22 @@ type1(int *msgvec, int doign, int mime_decode)
#endif
(void)thread_recursion(mp, type1_core, &args);
}
#ifdef MIME_SUPPORT
close_pipe:
#ifdef MIME_SUPPORT
if (mip != NULL) {
struct sigaction osa;
sigset_t oset;
/*
* Ignore SIGPIPE so it can't cause a duplicate close.
*/
(void)signal(SIGPIPE, SIG_IGN);
(void)sig_ignore(SIGPIPE, &osa, &oset);
mime_decode_close(mip);
(void)signal(SIGPIPE, oldsigpipe);
(void)sig_restore(SIGPIPE, &osa, &oset);
}
#endif
(void)sig_signal(SIGPIPE, oldsigpipe);
sig_check();
return 0;
}
@ -367,6 +387,7 @@ close_pipe:
static int
de_mime(void)
{
return value(ENAME_MIME_DECODE_MSG) != NULL;
}
@ -376,7 +397,9 @@ de_mime(void)
PUBLIC int
view(void *v)
{
int *msgvec = v;
int *msgvec;
msgvec = v;
return type1(msgvec, 1, !de_mime());
}
@ -386,8 +409,9 @@ view(void *v)
PUBLIC int
View(void *v)
{
int *msgvec = v;
int *msgvec;
msgvec = v;
return type1(msgvec, 0, !de_mime());
}
#endif /* MIME_SUPPORT */
@ -398,8 +422,9 @@ View(void *v)
PUBLIC int
type(void *v)
{
int *msgvec = v;
int *msgvec;
msgvec = v;
return type1(msgvec, 1, de_mime());
}
@ -409,8 +434,9 @@ type(void *v)
PUBLIC int
Type(void *v)
{
int *msgvec = v;
int *msgvec;
msgvec = v;
return type1(msgvec, 0, de_mime());
}
@ -420,9 +446,11 @@ Type(void *v)
PUBLIC int
pipecmd(void *v)
{
char *cmd = v;
FILE *volatile obuf; /* void longjmp clobbering - we want
the current value not start value */
char *cmd;
FILE *volatile obuf; /* void longjmp clobbering */
sig_t volatile oldsigpipe; /* XXX - is volatile needed? */
cmd = v;
if (dot == NULL) {
warn("pipcmd: no current message");
return 1;
@ -432,30 +460,36 @@ pipecmd(void *v)
if (setjmp(pipestop))
goto close_pipe;
sig_check();
obuf = Popen(cmd, "w");
if (obuf == NULL) {
warn("pipecmd: Popen failed: %s", cmd);
return 1;
} else
(void)signal(SIGPIPE, brokpipe);
}
oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
(void)sendmessage(dot, obuf, ignoreall, NULL, NULL);
close_pipe:
sig_check();
if (obuf != stdout) {
struct sigaction osa;
sigset_t oset;
/*
* Ignore SIGPIPE so it can't cause a duplicate close.
*/
(void)signal(SIGPIPE, SIG_IGN);
(void)sig_ignore(SIGPIPE, &osa, &oset);
(void)Pclose(obuf);
(void)signal(SIGPIPE, SIG_DFL);
(void)sig_restore(SIGPIPE, &osa, &oset);
}
(void)sig_signal(SIGPIPE, oldsigpipe);
sig_check();
return 0;
}
struct top_core_args_s {
int lineb;
int topl;
size_t topl;
struct message *parent;
};
static int
@ -464,8 +498,8 @@ top_core(struct message *mp, void *v)
char buffer[LINESIZE];
struct top_core_args_s *args;
FILE *ibuf;
int lines;
int c;
size_t lines;
size_t c;
args = v;
touch(mp);
@ -475,11 +509,13 @@ top_core(struct message *mp, void *v)
ibuf = setinput(mp);
c = mp->m_lines;
for (lines = 0; lines < c && lines <= args->topl; lines++) {
if (mail_readline(ibuf, buffer, sizeof(buffer)) < 0)
sig_check();
if (readline(ibuf, buffer, (int)sizeof(buffer), 0) < 0)
break;
(void)puts(buffer);
args->lineb = blankline(buffer);
}
sig_check();
return 0;
}
@ -494,11 +530,12 @@ top(void *v)
struct top_core_args_s args;
int recursive;
int msgCount;
int *msgvec = v;
int *msgvec;
int *ip;
int topl;
char *valtop;
msgvec = v;
topl = 5;
valtop = value(ENAME_TOPLINES);
if (valtop != NULL) {
@ -528,12 +565,14 @@ top(void *v)
PUBLIC int
stouch(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
for (ip = msgvec; *ip != 0; ip++)
msgvec = v;
for (ip = msgvec; *ip != 0; ip++) {
sig_check();
dot = set_m_flag(*ip, ~(MPRESERVE | MTOUCH), MTOUCH);
}
return 0;
}
@ -543,13 +582,15 @@ stouch(void *v)
PUBLIC int
mboxit(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
for (ip = msgvec; *ip != 0; ip++)
msgvec = v;
for (ip = msgvec; *ip != 0; ip++) {
sig_check();
dot = set_m_flag(*ip,
~(MPRESERVE | MTOUCH | MBOX), MTOUCH | MBOX);
}
return 0;
}
@ -569,7 +610,7 @@ folders(void *v __unused)
}
if ((cmd = value(ENAME_LISTER)) == NULL)
cmd = "ls";
(void)run_command(cmd, 0, -1, -1, dirname, NULL);
(void)run_command(cmd, NULL, -1, -1, dirname, NULL);
return 0;
}
@ -581,7 +622,8 @@ folders(void *v __unused)
PUBLIC int
inc(void *v __unused)
{
int nmsg, mdot;
int nmsg;
int mdot;
nmsg = incfile();
@ -595,6 +637,5 @@ inc(void *v __unused)
} else {
(void)printf("\"inc\" command failed...\n");
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmd2.c,v 1.23 2007/10/27 15:14:50 christos Exp $ */
/* $NetBSD: cmd2.c,v 1.24 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)cmd2.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: cmd2.c,v 1.23 2007/10/27 15:14:50 christos Exp $");
__RCSID("$NetBSD: cmd2.c,v 1.24 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
@ -60,11 +60,12 @@ __RCSID("$NetBSD: cmd2.c,v 1.23 2007/10/27 15:14:50 christos Exp $");
PUBLIC int
next(void *v)
{
int *msgvec = v;
int *msgvec;
struct message *mp;
int *ip, *ip2;
int list[2], mdot;
msgvec = v;
if (*msgvec != 0) {
/*
@ -151,15 +152,13 @@ snarf(char linebuf[], int *flag, const char *string)
/*
* Strip away trailing blanks.
*/
while (cp > linebuf && isspace((unsigned char)*cp))
while (cp >= linebuf && isspace((unsigned char)*cp))
cp--;
*++cp = 0;
*++cp = '\0';
/*
* Now search for the beginning of the file name.
*/
while (cp > linebuf && !isspace((unsigned char)*cp))
cp--;
if (*cp == '\0') {
@ -167,7 +166,7 @@ snarf(char linebuf[], int *flag, const char *string)
return NULL;
}
if (isspace((unsigned char)*cp))
*cp++ = 0;
*cp++ = '\0';
else
*flag = 0;
return cp;
@ -182,8 +181,8 @@ static int
save1_core(struct message *mp, void *v)
{
struct save1_core_args_s *args;
args = v;
args = v;
touch(mp);
if (sendmessage(mp, args->obuf, args->igtab, NULL, NULL) < 0)
@ -264,8 +263,9 @@ save1(char str[], int markmsg, const char *cmd, struct ignoretab *igtab)
PUBLIC int
save(void *v)
{
char *str = v;
char *str;
str = v;
return save1(str, 1, "save", saveignore);
}
@ -277,8 +277,9 @@ save(void *v)
PUBLIC int
Save(void *v)
{
char *str = v;
char *str;
str = v;
return save1(str, 1, "Save", NULL);
}
@ -288,8 +289,9 @@ Save(void *v)
PUBLIC int
copycmd(void *v)
{
char *str = v;
char *str;
str = v;
return save1(str, 0, "copy", saveignore);
}
@ -300,8 +302,9 @@ copycmd(void *v)
PUBLIC int
swrite(void *v)
{
char *str = v;
char *str;
str = v;
return save1(str, 1, "write", ignoreall);
}
@ -349,7 +352,9 @@ delm(int *msgvec)
PUBLIC int
delete(void *v)
{
int *msgvec = v;
int *msgvec;
msgvec = v;
(void)delm(msgvec);
return 0;
}
@ -360,10 +365,11 @@ delete(void *v)
PUBLIC int
deltype(void *v)
{
int *msgvec = v;
int *msgvec;
int list[2];
int lastdot;
msgvec = v;
lastdot = get_msgnum(dot);
if (delm(msgvec) >= 0) {
list[0] = get_msgnum(dot);
@ -449,9 +455,10 @@ clob1(int n)
PUBLIC int
clobber(void *v)
{
char **argv = v;
char **argv;
int times;
argv = v;
if (argv[0] == 0)
times = 1;
else
@ -519,8 +526,9 @@ ignore1(char *list[], struct ignoretab *tab, const char *which)
PUBLIC int
retfield(void *v)
{
char **list = v;
char **list;
list = v;
return ignore1(list, ignore + 1, "retained");
}
@ -531,8 +539,9 @@ retfield(void *v)
PUBLIC int
igfield(void *v)
{
char **list = v;
char **list;
list = v;
return ignore1(list, ignore, "ignored");
}
@ -543,8 +552,9 @@ igfield(void *v)
PUBLIC int
saveretfield(void *v)
{
char **list = v;
char **list;
list = v;
return ignore1(list, saveignore + 1, "retained");
}
@ -555,8 +565,9 @@ saveretfield(void *v)
PUBLIC int
saveigfield(void *v)
{
char **list = v;
char **list;
list = v;
return ignore1(list, saveignore, "ignored");
}
@ -595,7 +606,7 @@ check_dirname(char *filename)
if (access(canon_name, W_OK|X_OK) == -1) {
warnx("access: %s is not writable", canon_name);
canon_name = NULL;
/* goto done; */
goto done;
}
done:
if (fname != filename)
@ -604,7 +615,6 @@ check_dirname(char *filename)
return canon_name ? savestr(canon_name) : NULL;
}
struct detach1_core_args_s {
struct message *parent;
struct ignoretab *igtab;
@ -683,6 +693,7 @@ detach1(void *v, int do_unnamed)
for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
struct detach1_core_args_s args;
struct message *mp;
mp = get_message(*ip);
dot = mp;
args.parent = recursive ? mp : NULL;
@ -699,6 +710,7 @@ detach1(void *v, int do_unnamed)
PUBLIC int
detach(void *v)
{
return detach1(v, 0);
}
@ -708,6 +720,7 @@ detach(void *v)
PUBLIC int
Detach(void *v)
{
return detach1(v, 1);
}
#endif /* MIME_SUPPORT */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmd3.c,v 1.39 2007/10/30 16:08:11 christos Exp $ */
/* $NetBSD: cmd3.c,v 1.40 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: cmd3.c,v 1.39 2007/10/30 16:08:11 christos Exp $");
__RCSID("$NetBSD: cmd3.c,v 1.40 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
@ -43,6 +43,7 @@ __RCSID("$NetBSD: cmd3.c,v 1.39 2007/10/30 16:08:11 christos Exp $");
#include <util.h>
#include "extern.h"
#include "mime.h"
#include "sig.h"
#include "thread.h"
/*
@ -59,6 +60,7 @@ __RCSID("$NetBSD: cmd3.c,v 1.39 2007/10/30 16:08:11 christos Exp $");
static int
diction(const void *a, const void *b)
{
return strcmp(*(const char *const *)a, *(const char *const *)b);
}
@ -73,9 +75,9 @@ sort(const char **list)
for (ap = list; *ap != NULL; ap++)
continue;
if (ap-list < 2)
if (ap - list < 2)
return;
qsort(list, (size_t)(ap-list), sizeof(*list), diction);
qsort(list, (size_t)(ap - list), sizeof(*list), diction);
}
/*
@ -88,16 +90,17 @@ bangexp(char *str)
static char lastbang[128];
char bangbuf[LINESIZE];
char *cp, *cp2;
int n;
int changed = 0;
ssize_t n;
int changed;
changed = 0;
cp = str;
cp2 = bangbuf;
n = sizeof(bangbuf); /* bytes left in bangbuf */
while (*cp) {
if (*cp == '!') {
if (n < (int)strlen(lastbang)) {
overf:
overf:
(void)printf("Command buffer overflow\n");
return -1;
}
@ -136,19 +139,24 @@ overf:
PUBLIC int
shell(void *v)
{
char *str = v;
sig_t sigint = signal(SIGINT, SIG_IGN);
struct sigaction osa;
sigset_t oset;
char *str;
const char *shellcmd;
char cmd[LINESIZE];
str = v;
sig_check();
(void)sig_ignore(SIGINT, &osa, &oset);
(void)strcpy(cmd, str);
if (bangexp(cmd) < 0)
return 1;
if ((shellcmd = value(ENAME_SHELL)) == NULL)
shellcmd = _PATH_CSHELL;
(void)run_command(shellcmd, 0, 0, 1, "-c", cmd, NULL);
(void)signal(SIGINT, sigint);
(void)run_command(shellcmd, NULL, 0, 1, "-c", cmd, NULL);
(void)sig_restore(SIGINT, &osa, &oset);
(void)printf("!\n");
sig_check();
return 0;
}
@ -159,14 +167,18 @@ shell(void *v)
PUBLIC int
dosh(void *v __unused)
{
sig_t sigint = signal(SIGINT, SIG_IGN);
struct sigaction osa;
sigset_t oset;
const char *shellcmd;
sig_check();
(void)sig_ignore(SIGINT, &osa, &oset);
if ((shellcmd = value(ENAME_SHELL)) == NULL)
shellcmd = _PATH_CSHELL;
(void)run_command(shellcmd, 0, 0, 1, NULL);
(void)signal(SIGINT, sigint);
(void)run_command(shellcmd, NULL, 0, 1, NULL);
(void)sig_restore(SIGINT, &osa, &oset);
(void)putchar('\n');
sig_check();
return 0;
}
@ -178,6 +190,7 @@ dosh(void *v __unused)
PUBLIC int
help(void *v __unused)
{
cathelp(_PATH_HELP);
return 0;
}
@ -188,9 +201,10 @@ help(void *v __unused)
PUBLIC int
schdir(void *v)
{
char **arglist = v;
char **arglist;
const char *cp;
arglist = v;
if (*arglist == NULL)
cp = homedir;
else
@ -210,9 +224,11 @@ static struct name *
set_smopts(struct message *mp)
{
char *cp;
struct name *np = NULL;
char *reply_as_recipient = value(ENAME_REPLYASRECIPIENT);
struct name *np;
char *reply_as_recipient;
np = NULL;
reply_as_recipient = value(ENAME_REPLYASRECIPIENT);
if (reply_as_recipient &&
(cp = skin(hfield("to", mp))) != NULL &&
extract(cp, GTO)->n_flink == NULL) { /* check for one recipient */
@ -540,12 +556,13 @@ bounce_one(int msgno, const char **smargs, struct name *h_to)
PUBLIC int
bounce(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
const char **smargs;
struct header hdr;
int rval;
msgvec = v;
if (bouncetab[0].i_count == 0) {
/* setup the bounce tab */
add_ignore("Status", bouncetab);
@ -576,9 +593,10 @@ bounce(void *v)
PUBLIC int
preserve(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
msgvec = v;
if (edit) {
(void)printf("Cannot \"preserve\" in edit mode\n");
return 1;
@ -595,9 +613,10 @@ preserve(void *v)
PUBLIC int
unread(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
msgvec = v;
for (ip = msgvec; *ip != 0; ip++)
dot = set_m_flag(*ip, ~(MREAD | MTOUCH | MSTATUS), MSTATUS);
@ -610,9 +629,10 @@ unread(void *v)
PUBLIC int
markread(void *v)
{
int *msgvec = v;
int *msgvec;
int *ip;
msgvec = v;
for (ip = msgvec; *ip != 0; ip++)
dot = set_m_flag(*ip,
~(MNEW | MTOUCH | MREAD | MSTATUS), MREAD | MSTATUS);
@ -626,10 +646,11 @@ markread(void *v)
PUBLIC int
messize(void *v)
{
int *msgvec = v;
int *msgvec;
struct message *mp;
int *ip, mesg;
msgvec = v;
for (ip = msgvec; *ip != 0; ip++) {
mesg = *ip;
mp = get_message(mesg);

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmd4.c,v 1.4 2008/04/28 20:24:14 martin Exp $ */
/* $NetBSD: cmd4.c,v 1.5 2009/04/10 13:08:24 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
#if 0
static char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: cmd4.c,v 1.4 2008/04/28 20:24:14 martin Exp $");
__RCSID("$NetBSD: cmd4.c,v 1.5 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
@ -55,6 +55,7 @@ void showname(struct name *);
void
showname(struct name *np)
{
for (/*EMPTY*/; np; np = np->n_flink)
(void)printf("np: %p np->n_type: %d np->n_name: '%s' (%p)\n",
np, np->n_type, np->n_name, np->n_name);
@ -64,6 +65,7 @@ __unused
static void
showsmopts(struct smopts_s *sp)
{
(void)printf("%s (%p)\n", sp->s_name, sp);
showname(sp->s_smopts);
}
@ -74,6 +76,7 @@ static int
hashcase(const char *key)
{
char *lckey;
lckey = salloc(strlen(key) + 1);
istrcpy(lckey, key);
return hash(lckey);
@ -128,18 +131,19 @@ static void
printsmoptstbl(void)
{
struct smopts_s *sp;
const char **argv, **ap;
const char **argv;
const char **ap;
int h;
int cnt;
cnt = 1;
for (h = 0; h < (int)sizeofarray(smoptstbl); h++ )
for (h = 0; h < (int)__arraycount(smoptstbl); h++ )
for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
cnt++;
argv = salloc(cnt * sizeof(*argv));
ap = argv;
for (h = 0; h < (int)sizeofarray(smoptstbl); h++ )
for (h = 0; h < (int)__arraycount(smoptstbl); h++ )
for (sp = smoptstbl[h]; sp && sp->s_name != NULL; sp = sp->s_link)
*ap++ = sp->s_name;
*ap = NULL;
@ -180,7 +184,8 @@ static void
smopts_core(const char *sname, char **argv)
{
struct smopts_s *sp;
struct name *np, *t;
struct name *np;
struct name *t;
int h;
char **ap;
@ -217,8 +222,9 @@ PUBLIC int
smoptscmd(void *v)
{
struct name *np;
char **argv = v;
char **argv;
argv = v;
if (*argv == NULL) {
printsmoptstbl();
return 0;
@ -240,6 +246,7 @@ static void
free_name(struct name *np)
{
struct name *next_np;
for (/*EMPTY*/; np; np = next_np) {
next_np = np->n_flink;
free(next_np);
@ -269,11 +276,112 @@ PUBLIC int
unsmoptscmd(void *v)
{
struct name *np;
char **argv, **ap;
char **ap;
argv = v;
for (ap = argv; *ap != NULL; ap++)
for (ap = v; *ap != NULL; ap++)
for (np = name_expand(*ap, GTO); np; np = np->n_flink)
delsmopts(np->n_name);
return 0;
}
static struct name *
alloc_Header(char *str)
{
struct name *np;
/*
* Don't use salloc() routines here as these strings must persist.
*/
np = ecalloc(1, sizeof(*np));
np->n_name = estrdup(str);
np->n_type = GMISC;
return np;
}
static int
free_Header(char *str)
{
struct name *np;
struct name *next_np;
size_t len;
len = strlen(str);
for (np = extra_headers; np != NULL; np = next_np) {
next_np = np->n_flink;
if (strncasecmp(np->n_name, str, len) == 0) {
if (np == extra_headers) {
extra_headers = np->n_flink;
if (extra_headers)
extra_headers->n_blink = NULL;
}
else {
struct name *bp;
struct name *fp;
bp = np->n_blink;
fp = np->n_flink;
if (bp)
bp->n_flink = fp;
if (fp)
fp->n_blink = bp;
}
if (np->n_name)
free(np->n_name);
free(np);
}
}
return 0;
}
/*
* Takes a string and includes it in the header.
*/
PUBLIC int
Header(void *v)
{
struct name *np;
char *str;
char *p;
str = v;
if (str == NULL)
return 0;
(void)strip_WSP(str); /* strip trailing whitespace */
if (str[0] == '\0') { /* Show the extra headers */
for (np = extra_headers; np != NULL; np = np->n_flink)
(void)printf("%s\n", np->n_name);
return 0;
}
/*
* Check for a valid header line: find the end of its name.
*/
for (p = str; *p != '\0' && *p != ':' && !is_WSP(*p); p++)
continue;
if (p[0] == ':' && p[1] == '\0') /* free headers of this type */
return free_Header(str);
/*
* Check for a valid header name.
*/
if (*p != ':' || !is_WSP(p[1])) {
(void)printf("invalid header string: `%s'\n", str);
return 0;
}
np = alloc_Header(str);
if (extra_headers == NULL)
extra_headers = np;
else {
struct name *tp;
for (tp = extra_headers; tp->n_flink; tp = tp->n_flink)
continue;
tp->n_flink = np;
np->n_blink = tp;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmdtab.c,v 1.20 2007/10/30 02:28:31 christos Exp $ */
/* $NetBSD: cmdtab.c,v 1.21 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: cmdtab.c,v 1.20 2007/10/30 02:28:31 christos Exp $");
__RCSID("$NetBSD: cmdtab.c,v 1.21 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
@ -62,7 +62,7 @@ __RCSID("$NetBSD: cmdtab.c,v 1.20 2007/10/30 02:28:31 christos Exp $");
/* R - in left comment means recursive */
const struct cmd cmdtab[] = {
{ "next", next, C, CMP(n) NDMLIST, 0, MMNDEL },
{ "alias", group, S, CMP(A) M|RAWLIST, 0, 1000 },
{ "alias", group, S, CMP(A) T|M|RAWLIST, 0, 1000 },
/* R */ { "print", type, C, CMP(n) MSGLIST, 0, MMNDEL },
/* R */ { "Print", Type, C, CMP(n) MSGLIST, 0, MMNDEL },
/* R */ { "type", type, C, CMP(n) MSGLIST, 0, MMNDEL },
@ -75,7 +75,7 @@ const struct cmd cmdtab[] = {
/* R */ { "dp", deltype, C, CMP(n) W|MSGLIST, 0, MMNDEL },
/* R */ { "dt", deltype, C, CMP(n) W|MSGLIST, 0, MMNDEL },
/* R */ { "undelete", undeletecmd, 0, CMP(n) P|MSGLIST, MDELETED, MMNDEL },
{ "unset", unset, 0, CMP(S) M|RAWLIST, 1, 1000 },
{ "unset", unset, 0, CMP(S) T|M|RAWLIST, 1, 1000 },
{ "mail", sendmail, 0, CMP(A) R|M|I|STRLIST, 0, 0 },
/* R */ { "mbox", mboxit, 0, CMP(n) W|MSGLIST, 0, MMNDEL },
/* R */ { "more", type, A, CMP(n) MSGLIST, 0, MMNDEL },
@ -86,21 +86,21 @@ const struct cmd cmdtab[] = {
/* R */ { "view", view, A, CMP(n) MSGLIST, 0, MMNDEL },
/* R */ { "View", View, A, CMP(n) MSGLIST, 0, MMNDEL },
#endif
{ "unalias", unalias, 0, CMP(A) M|RAWLIST, 1, 1000 },
{ "unalias", unalias, 0, CMP(A) T|M|RAWLIST, 1, 1000 },
/* R */ { "unread", unread, 0, CMP(n) MSGLIST, 0, MMNDEL },
{ "!", shell, 0, CMP(xF) I|STRLIST, 0, 0 },
{ "!", shell, 0, CMP(xF) T|I|STRLIST, 0, 0 },
{ "|", pipecmd, 0, CMP(xF) I|STRLIST, 0, 0 },
/* R */ { "copy", copycmd, 0, CMP(F) M|STRLIST, 0, 0 },
{ "chdir", schdir, 0, CMP(F) M|RAWLIST, 0, 1 },
{ "cd", schdir, 0, CMP(F) M|RAWLIST, 0, 1 },
{ "chdir", schdir, 0, CMP(F) T|M|RAWLIST, 0, 1 },
{ "cd", schdir, 0, CMP(F) T|M|RAWLIST, 0, 1 },
/* R */ { "save", save, 0, CMP(F) STRLIST, 0, 0 },
/* R */ { "Save", Save, 0, CMP(F) STRLIST, 0, 0 },
{ "source", source, 0, CMP(F) M|RAWLIST, 1, 1 },
{ "set", set, S, CMP(sF) M|RAWLIST, 0, 1000 },
{ "shell", dosh, 0, CMP(n) I|NOLIST, 0, 0 },
{ "show", show, S, CMP(S) M|RAWLIST, 0, 1000 },
{ "version", pversion, S, CMP(n) M|NOLIST, 0, 0 },
{ "group", group, S, CMP(a) M|RAWLIST, 0, 1000 },
{ "source", source, 0, CMP(F) T|M|RAWLIST, 1, 1 },
{ "set", set, S, CMP(sF) T|M|RAWLIST, 0, 1000 },
{ "shell", dosh, 0, CMP(n) T|I|NOLIST, 0, 0 },
{ "show", show, S, CMP(S) T|M|RAWLIST, 0, 1000 },
{ "version", pversion, S, CMP(n) T|M|NOLIST, 0, 0 },
{ "group", group, S, CMP(a) T|M|RAWLIST, 0, 1000 },
/* R */ { "write", swrite, 0, CMP(F) STRLIST, 0, 0 },
{ "from", from, S, CMP(n) MSGLIST, 0, MMNORM },
{ "file", file, 0, CMP(f) T|M|RAWLIST, 0, 1 },
@ -110,42 +110,42 @@ const struct cmd cmdtab[] = {
{ "forward", forward, 0, CMP(n) R|I|MSGLIST, 0, 0 },
#endif
{ "bounce", bounce, 0, CMP(n) R|I|MSGLIST, 0, 0 },
{ "?", help, S, CMP(n) M|NOLIST, 0, 0 },
{ "?", help, S, CMP(n) T|M|NOLIST, 0, 0 },
{ "z", scroll, S, CMP(n) M|STRLIST, 0, 0 },
{ "headers", headers, S, CMP(n) MSGLIST, 0, MMNDEL },
{ "help", help, S, CMP(n) M|NOLIST, 0, 0 },
{ "=", pdot, S, CMP(n) MSGLIST, 0, MMNDEL },
{ "headers", headers, S, CMP(n) T|MSGLIST, 0, MMNDEL },
{ "help", help, S, CMP(n) T|M|NOLIST, 0, 0 },
{ "=", pdot, S, CMP(n) T|MSGLIST, 0, MMNDEL },
{ "Reply", Respond, 0, CMP(n) R|I|MSGLIST, 0, MMNDEL },
{ "Respond", Respond, 0, CMP(n) R|I|MSGLIST, 0, MMNDEL },
{ "reply", respond, 0, CMP(n) R|I|MSGLIST, 0, MMNDEL },
{ "respond", respond, 0, CMP(n) R|I|MSGLIST, 0, MMNDEL },
{ "edit", editor, 0, CMP(n) I|MSGLIST, 0, MMNORM },
{ "echo", echo, S, CMP(F) M|RAWLIST, 0, 1000 },
{ "echo", echo, S, CMP(F) T|M|RAWLIST, 0, 1000 },
{ "quit", quitcmd, 0, CMP(n) NOLIST, 0, 0 },
{ "list", pcmdlist, S, CMP(n) M|NOLIST, 0, 0 },
{ "list", pcmdlist, S, CMP(n) T|M|NOLIST, 0, 0 },
{ "xit", rexit, 0, CMP(n) M|NOLIST, 0, 0 },
{ "exit", rexit, 0, CMP(n) M|NOLIST, 0, 0 },
{ "size", messize, S, CMP(n) MSGLIST, 0, MMNDEL },
{ "size", messize, S, CMP(n) T|MSGLIST, 0, MMNDEL },
/* R */ { "hold", preserve, 0, CMP(n) W|MSGLIST, 0, MMNDEL },
{ "if", ifcmd, 0, CMP(F) F|M|RAWLIST, 1, 1 },
{ "ifdef", ifdefcmd, 0, CMP(F) F|M|RAWLIST, 1, 1 },
{ "ifndef", ifndefcmd, 0, CMP(F) F|M|RAWLIST, 1, 1 },
{ "else", elsecmd, 0, CMP(F) F|M|RAWLIST, 0, 0 },
{ "endif", endifcmd, 0, CMP(F) F|M|RAWLIST, 0, 0 },
{ "alternates", alternates, S, CMP(n) M|RAWLIST, 0, 1000 },
{ "ignore", igfield, S, CMP(n) M|RAWLIST, 0, 1000 },
{ "discard", igfield, S, CMP(n) M|RAWLIST, 0, 1000 },
{ "retain", retfield, S, CMP(n) M|RAWLIST, 0, 1000 },
{ "saveignore", saveigfield, S, CMP(n) M|RAWLIST, 0, 1000 },
{ "savediscard",saveigfield, S, CMP(n) M|RAWLIST, 0, 1000 },
{ "saveretain", saveretfield, S, CMP(n) M|RAWLIST, 0, 1000 },
/* { "Header", Header, S, CMP(n) STRLIST, 0, 1000 }, */
{ "core", core, 0, CMP(F) M|NOLIST, 0, 0 },
{ "#", null, 0, CMP(n) M|NOLIST, 0, 0 },
{ "clobber", clobber, 0, CMP(n) M|RAWLIST, 0, 1 },
{ "if", ifcmd, 0, CMP(F) T|F|M|RAWLIST, 1, 1 },
{ "ifdef", ifdefcmd, 0, CMP(F) T|F|M|RAWLIST, 1, 1 },
{ "ifndef", ifndefcmd, 0, CMP(F) T|F|M|RAWLIST, 1, 1 },
{ "else", elsecmd, 0, CMP(F) T|F|M|RAWLIST, 0, 0 },
{ "endif", endifcmd, 0, CMP(F) T|F|M|RAWLIST, 0, 0 },
{ "alternates", alternates, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "ignore", igfield, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "discard", igfield, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "retain", retfield, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "saveignore", saveigfield, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "savediscard",saveigfield, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "saveretain", saveretfield, S, CMP(n) T|M|RAWLIST, 0, 1000 },
{ "Header", Header, S, CMP(n) T|M|STRLIST, 0, 1000 },
{ "core", core, 0, CMP(F) T|M|NOLIST, 0, 0 },
{ "#", null, 0, CMP(n) T|M|NOLIST, 0, 0 },
{ "clobber", clobber, 0, CMP(n) T|M|RAWLIST, 0, 1 },
{ "inc", inc, S, CMP(n) T|NOLIST, 0, 0 },
{ "smopts", smoptscmd, S, CMP(m) M|RAWLIST, 0, 1000 },
{ "unsmopts", unsmoptscmd, S, CMP(M) M|RAWLIST, 1, 1000 },
{ "smopts", smoptscmd, S, CMP(m) T|M|RAWLIST, 0, 1000 },
{ "unsmopts", unsmoptscmd, S, CMP(M) T|M|RAWLIST, 1, 1000 },
/* R */ { "mkread", markread, 0, CMP(n) MSGLIST, 0, MMNDEL },
#ifdef MIME_SUPPORT
/* R */ { "detach", detach, S, CMP(F) STRLIST, 0, 0 },

View File

@ -1,4 +1,4 @@
/* $NetBSD: collect.c,v 1.42 2007/10/29 23:20:38 christos Exp $ */
/* $NetBSD: collect.c,v 1.43 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)collect.c 8.2 (Berkeley) 4/19/94";
#else
__RCSID("$NetBSD: collect.c,v 1.42 2007/10/29 23:20:38 christos Exp $");
__RCSID("$NetBSD: collect.c,v 1.43 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
@ -54,6 +54,7 @@ __RCSID("$NetBSD: collect.c,v 1.42 2007/10/29 23:20:38 christos Exp $");
#ifdef MIME_SUPPORT
#include "mime.h"
#endif
#include "sig.h"
#include "thread.h"
@ -67,19 +68,12 @@ __RCSID("$NetBSD: collect.c,v 1.42 2007/10/29 23:20:38 christos Exp $");
* receipt of an interrupt signal, the partial message can be salted
* away on dead.letter.
*/
static sig_t saveint; /* Previous SIGINT value */
static sig_t savehup; /* Previous SIGHUP value */
static sig_t savetstp; /* Previous SIGTSTP value */
static sig_t savettou; /* Previous SIGTTOU value */
static sig_t savettin; /* Previous SIGTTIN value */
static FILE *collf; /* File for saving away */
static int hadintr; /* Have seen one SIGINT so far */
static jmp_buf colljmp; /* To get back to work */
static int colljmp_p; /* whether to long jump */
static jmp_buf collabort; /* To end collection with error */
static jmp_buf abort_jmpbuf; /* To end collection with error */
static jmp_buf reset_jmpbuf; /* To get back to work */
static int reset_on_stop; /* To do job control longjmp. */
/*
* Write a file, ex-like if f set.
@ -133,15 +127,20 @@ exwrite(const char name[], FILE *fp, int f)
static void
mesedit(FILE *fp, int c)
{
sig_t sigint = signal(SIGINT, SIG_IGN);
FILE *nf = run_editor(fp, (off_t)-1, c, 0);
struct sigaction osa;
sigset_t oset;
FILE *nf;
sig_check();
(void)sig_ignore(SIGINT, &osa, &oset);
nf = run_editor(fp, (off_t)-1, c, 0);
if (nf != NULL) {
(void)fseek(nf, 0L, 2);
collf = nf;
(void)Fclose(fp);
}
(void)signal(SIGINT, sigint);
(void)sig_restore(SIGINT, &osa, &oset);
sig_check();
}
/*
@ -154,11 +153,15 @@ static void
mespipe(FILE *fp, char cmd[])
{
FILE *nf;
sig_t sigint = signal(SIGINT, SIG_IGN);
struct sigaction osa;
sigset_t oset;
const char *shellcmd;
int fd;
char tempname[PATHSIZE];
sig_check();
(void)sig_ignore(SIGINT, &osa, &oset);
(void)snprintf(tempname, sizeof(tempname),
"%s/mail.ReXXXXXXXXXX", tmpdir);
if ((fd = mkstemp(tempname)) == -1 ||
@ -176,7 +179,7 @@ mespipe(FILE *fp, char cmd[])
if ((shellcmd = value(ENAME_SHELL)) == NULL)
shellcmd = _PATH_CSHELL;
if (run_command(shellcmd,
0, fileno(fp), fileno(nf), "-c", cmd, NULL) < 0) {
NULL, fileno(fp), fileno(nf), "-c", cmd, NULL) < 0) {
(void)Fclose(nf);
goto out;
}
@ -191,8 +194,9 @@ mespipe(FILE *fp, char cmd[])
(void)fseek(nf, 0L, 2);
collf = nf;
(void)Fclose(fp);
out:
(void)signal(SIGINT, sigint);
out:
(void)sig_restore(SIGINT, &osa, &oset);
sig_check();
}
/*
@ -267,29 +271,6 @@ interpolate(char ms[], FILE *fp, char *fn, int f)
return 0;
}
/*
* Print (continue) when continued after ^Z.
*/
/*ARGSUSED*/
static void
collstop(int s)
{
sig_t old_action = signal(s, SIG_DFL);
sigset_t nset;
(void)sigemptyset(&nset);
(void)sigaddset(&nset, s);
(void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
(void)kill(0, s);
(void)sigprocmask(SIG_BLOCK, &nset, NULL);
(void)signal(s, old_action);
if (colljmp_p) {
colljmp_p = 0;
hadintr = 0;
longjmp(colljmp, 1);
}
}
/*
* Append the contents of the file to the end of the deadletter file.
*/
@ -309,6 +290,7 @@ savedeadletter(FILE *fp)
(void)umask(m);
if (dbuf == NULL)
return;
(void)printf("Saving message body to `%s'.\n", cp);
while ((c = getc(fp)) != EOF)
(void)putc(c, dbuf);
(void)Fclose(dbuf);
@ -319,10 +301,10 @@ savedeadletter(FILE *fp)
* On interrupt, come here to save the partial message in ~/dead.letter.
* Then jump out of the collection loop.
*/
/*ARGSUSED*/
static void
collint(int s __unused)
coll_int(int signo)
{
/*
* the control flow is subtle, because we can be called from ~q.
*/
@ -334,30 +316,50 @@ collint(int s __unused)
return;
}
hadintr = 1;
longjmp(colljmp, 1);
longjmp(reset_jmpbuf, signo);
}
rewind(collf);
if (value(ENAME_NOSAVE) == NULL)
savedeadletter(collf);
longjmp(collabort, 1);
longjmp(abort_jmpbuf, signo);
}
/*ARGSUSED*/
static void
collhup(int s __unused)
coll_hup(int signo __unused)
{
rewind(collf);
savedeadletter(collf);
/*
* Let's pretend nobody else wants to clean up,
* a true statement at this time.
*/
exit(1);
exit(EXIT_FAILURE);
}
/*
* Print (continue) when continued after ^Z.
*/
static void
coll_stop(int signo)
{
if (reset_on_stop) {
reset_on_stop = 0;
hadintr = 0;
longjmp(reset_jmpbuf, signo);
}
}
PUBLIC FILE *
collect(struct header *hp, int printheaders)
{
volatile sig_t old_sigint;
volatile sig_t old_sighup;
volatile sig_t old_sigtstp;
volatile sig_t old_sigttin;
volatile sig_t old_sigttou;
FILE *fbuf;
int lc, cc;
int c, fd, t;
@ -365,11 +367,10 @@ collect(struct header *hp, int printheaders)
const char *cp;
char tempname[PATHSIZE];
char mailtempname[PATHSIZE];
int lastlong, rc; /* So we don't make 2 or more lines
out of a long input line. */
int eofcount;
int longline;
sigset_t nset;
int lastlong, rc; /* So we don't make 2 or more lines
out of a long input line. */
/* The following are declared volatile to avoid longjmp clobbering. */
char volatile getsub;
@ -377,26 +378,20 @@ collect(struct header *hp, int printheaders)
(void)memset(mailtempname, 0, sizeof(mailtempname));
collf = NULL;
/*
* Start catching signals from here, but we're still die on interrupts
* until we're in the main loop.
*/
(void)sigemptyset(&nset);
(void)sigaddset(&nset, SIGINT);
(void)sigaddset(&nset, SIGHUP);
(void)sigprocmask(SIG_BLOCK, &nset, NULL);
if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
(void)signal(SIGINT, collint);
if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN)
(void)signal(SIGHUP, collhup);
savetstp = signal(SIGTSTP, collstop);
savettou = signal(SIGTTOU, collstop);
savettin = signal(SIGTTIN, collstop);
if (setjmp(collabort) || setjmp(colljmp)) {
if (setjmp(abort_jmpbuf) || setjmp(reset_jmpbuf)) {
(void)rm(mailtempname);
goto err;
}
(void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
sig_check();
sig_hold();
old_sigint = sig_signal(SIGINT, coll_int);
old_sighup = sig_signal(SIGHUP, coll_hup);
old_sigtstp = sig_signal(SIGTSTP, coll_stop);
old_sigttin = sig_signal(SIGTTIN, coll_stop);
old_sigttou = sig_signal(SIGTTOU, coll_stop);
sig_release();
noreset++;
(void)snprintf(mailtempname, sizeof(mailtempname),
@ -415,11 +410,13 @@ collect(struct header *hp, int printheaders)
* refrain from printing a newline after
* the headers (since some people mind).
*/
t = GTO|GSUBJECT|GCC|GNL|GSMOPTS;
t = GTO | GSUBJECT | GCC | GNL | GSMOPTS;
getsub = 0;
if (hp->h_subject == NULL && value(ENAME_INTERACTIVE) != NULL &&
(value(ENAME_ASK) != NULL || value(ENAME_ASKSUB) != NULL))
t &= ~GNL, getsub++;
(value(ENAME_ASK) != NULL || value(ENAME_ASKSUB) != NULL)) {
t &= ~GNL;
getsub++;
}
if (printheaders) {
(void)puthead(hp, stdout, t);
(void)fflush(stdout);
@ -428,8 +425,8 @@ collect(struct header *hp, int printheaders)
escape = *cp;
else
escape = ESCAPE;
hadintr = 0; /* static - no longjmp problem */
if (!setjmp(colljmp)) {
hadintr = 0;
if (setjmp(reset_jmpbuf) == 0) {
if (getsub)
(void)grabh(hp, GSUBJECT);
} else {
@ -438,7 +435,7 @@ collect(struct header *hp, int printheaders)
* Duplicate messages won't be printed because
* the write is aborted if we get a SIGTTOU.
*/
cont:
cont:
if (hadintr) {
(void)fflush(stdout);
(void)fprintf(stderr,
@ -451,12 +448,13 @@ cont:
eofcount = 0; /* reset after possible longjmp */
longline = 0; /* reset after possible longjmp */
for (;;) {
colljmp_p = 1;
c = mail_readline(stdin, linebuf, LINESIZE);
colljmp_p = 0;
#ifdef USE_EDITLINE
reset_on_stop = 1;
c = readline(stdin, linebuf, LINESIZE, reset_on_stop);
reset_on_stop = 0;
if (c < 0) {
char *p;
if (value(ENAME_INTERACTIVE) != NULL &&
(p = value(ENAME_IGNOREEOF)) != NULL &&
++eofcount < (*p == 0 ? 25 : atoi(p))) {
@ -465,18 +463,8 @@ cont:
}
break;
}
#else
if (c < 0) {
if (value(ENAME_INTERACTIVE) != NULL &&
value(ENAME_IGNOREEOF) != NULL && ++eofcount < 25) {
(void)printf("Use \".\" to terminate letter\n");
continue;
}
break;
}
#endif
lastlong = longline;
longline = c == LINESIZE-1;
longline = c == LINESIZE - 1;
eofcount = 0;
hadintr = 0;
if (linebuf[0] == '.' && linebuf[1] == '\0' &&
@ -540,7 +528,7 @@ cont:
* Act like an interrupt happened.
*/
hadintr++;
collint(SIGINT);
coll_int(SIGINT);
exit(1);
/*NOTREACHED*/
@ -551,7 +539,7 @@ cont:
/*
* Grab a bunch of headers.
*/
(void)grabh(hp, GTO|GSUBJECT|GCC|GBCC|GSMOPTS);
(void)grabh(hp, GTO | GSUBJECT | GCC | GBCC | GSMOPTS);
goto cont;
case 't':
/*
@ -651,7 +639,7 @@ cont:
if ((shellcmd = value(ENAME_SHELL)) == NULL)
shellcmd = _PATH_CSHELL;
rc2 = run_command(shellcmd, 0, nullfd, fileno(fbuf), "-c", cp + 1, NULL);
rc2 = run_command(shellcmd, NULL, nullfd, fileno(fbuf), "-c", cp + 1, NULL);
(void)close(nullfd);
@ -680,7 +668,7 @@ cont:
(void)fflush(stdout);
lc = 0;
cc = 0;
while ((rc = mail_readline(fbuf, linebuf, LINESIZE)) >= 0) {
while ((rc = readline(fbuf, linebuf, LINESIZE, 0)) >= 0) {
if (rc != LINESIZE-1) lc++;
if ((t = putline(collf, linebuf,
rc != LINESIZE-1)) < 0) {
@ -729,7 +717,8 @@ cont:
*/
rewind(collf);
(void)printf("-------\nMessage contains:\n");
(void)puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
(void)puthead(hp, stdout,
GTO | GSUBJECT | GCC | GBCC | GSMOPTS | GNL);
while ((t = getc(collf)) != EOF)
(void)putchar(t);
goto cont;
@ -754,21 +743,24 @@ cont:
}
}
goto out;
err:
err:
if (collf != NULL) {
(void)Fclose(collf);
collf = NULL;
}
out:
out:
if (collf != NULL)
rewind(collf);
noreset--;
(void)sigprocmask(SIG_BLOCK, &nset, NULL);
(void)signal(SIGINT, saveint);
(void)signal(SIGHUP, savehup);
(void)signal(SIGTSTP, savetstp);
(void)signal(SIGTTOU, savettou);
(void)signal(SIGTTIN, savettin);
(void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
sig_hold();
(void)sig_signal(SIGINT, old_sigint);
(void)sig_signal(SIGHUP, old_sighup);
(void)sig_signal(SIGTSTP, old_sigtstp);
(void)sig_signal(SIGTTIN, old_sigttin);
(void)sig_signal(SIGTTOU, old_sigttou);
sig_release();
sig_check();
return collf;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: complete.c,v 1.18 2009/02/11 19:22:22 christos Exp $ */
/* $NetBSD: complete.c,v 1.19 2009/04/10 13:08:24 christos Exp $ */
/*-
* Copyright (c) 1997-2000,2005,2006 The NetBSD Foundation, Inc.
@ -34,11 +34,10 @@
*/
#ifdef USE_EDITLINE
#undef NO_EDITCOMPLETE
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: complete.c,v 1.18 2009/02/11 19:22:22 christos Exp $");
__RCSID("$NetBSD: complete.c,v 1.19 2009/04/10 13:08:24 christos Exp $");
#endif /* not lint */
/*
@ -66,6 +65,7 @@ __RCSID("$NetBSD: complete.c,v 1.18 2009/02/11 19:22:22 christos Exp $");
#ifdef MIME_SUPPORT
#include "mime.h"
#endif
#include "sig.h"
#ifdef THREAD_SUPPORT
#include "thread.h"
#endif
@ -738,6 +738,7 @@ static int
is_emacs_mode(EditLine *el)
{
char *mode;
if (el_get(el, EL_EDITOR, &mode) == -1)
return 0;
return equal(mode, "emacs");
@ -747,6 +748,7 @@ static int
emacs_ctrl_d(EditLine *el, const LineInfo *lf, int ch)
{
static char delunder[3] = { CTRL('f'), CTRL('h'), '\0' };
if (ch == CTRL('d') && is_emacs_mode(el)) { /* CTRL-D is special */
if (lf->buffer == lf->lastchar)
return CC_EOF;
@ -882,7 +884,7 @@ split_word(int *cmpltype, const char *cmplarray, LineInfo *li)
}
/* check for 'continuation' completes (which are uppercase) */
arraylen = strlen(cmplarray);
arraylen = (int)strlen(cmplarray);
if (cursorc >= arraylen &&
arraylen > 0 &&
isupper((unsigned char)cmplarray[arraylen - 1]))
@ -1068,12 +1070,10 @@ mime_enc_complete(EditLine *el, int ch)
* Initializes of all editline and completion data strutures.
*
* my_gets()
* Returns the next line of input as a NULL termnated string without
* the trailing newline.
*
* my_getline()
* Same as my_gets(), but strips leading and trailing whitespace
* and returns an empty line if it gets a SIGINT.
* Displays prompt, calls el_gets() and deals with history.
* Returns the next line of input as a NULL termnated string
* without the trailing newline, or NULL if el_gets() sees is an
* error or signal.
*/
static const char *el_prompt;
@ -1085,30 +1085,68 @@ show_prompt(EditLine *e __unused)
return el_prompt;
}
/*
* Write the current INTR character to fp in a friendly form.
*/
static void
echo_INTR(void *p)
{
struct termios ttybuf;
char buf[5];
FILE *fp;
fp = p;
if (tcgetattr(fileno(stdin), &ttybuf) == -1)
warn("tcgetattr");
else {
(void)vis(buf, ttybuf.c_cc[VINTR], VIS_SAFE | VIS_NOSLASH, 0);
(void)fprintf(fp, "%s", buf);
(void)fflush(fp);
}
}
static sig_t old_sigint;
static void
comp_intr(int signo)
{
echo_INTR(stdout);
old_sigint(signo);
}
PUBLIC char *
my_gets(el_mode_t *em, const char *prompt, char *string)
{
int cnt;
static char line[LINE_MAX];
size_t len;
int cnt;
const char *buf;
HistEvent ev;
static char line[LINE_MAX];
sig_check();
el_prompt = prompt;
if (string)
el_push(em->el, string);
/*
* Let el_gets() deal with flow control. Also, make sure we
* output a ^C when we get a SIGINT as el_gets() doesn't echo
* one.
*/
old_sigint = sig_signal(SIGINT, comp_intr);
buf = el_gets(em->el, &cnt);
(void)sig_signal(SIGINT, old_sigint);
if (buf == NULL || cnt <= 0) {
if (cnt == 0)
(void)putc('\n', stdout);
if (buf == NULL) {
sig_check();
return NULL;
}
assert(cnt > 0);
if (buf[cnt - 1] == '\n')
cnt--; /* trash the trailing LF */
len = MIN(sizeof(line) - 1, (size_t)cnt);
(void)memcpy(line, buf, len);
line[cnt] = '\0';
@ -1116,56 +1154,15 @@ my_gets(el_mode_t *em, const char *prompt, char *string)
/* enter non-empty lines into history */
if (em->hist) {
const char *p;
p = skip_WSP(line);
if (*p && history(em->hist, &ev, H_ENTER, line) == 0)
(void)printf("Failed history entry: %s", line);
}
sig_check();
return line;
}
#ifdef MIME_SUPPORT
/* XXX - do we really want this here? */
static jmp_buf intjmp;
/*ARGSUSED*/
static void
sigint(int signum __unused)
{
siglongjmp(intjmp, 1);
}
PUBLIC char *
my_getline(el_mode_t *em, const char *prompt, const char *str)
{
sig_t saveint;
char *cp;
char *line;
saveint = signal(SIGINT, sigint);
if (sigsetjmp(intjmp, 1)) {
(void)signal(SIGINT, saveint);
(void)putc('\n', stdout);
return __UNCONST("");
}
line = my_gets(em, prompt, __UNCONST(str));
/* LINTED */
line = line ? savestr(line) : __UNCONST("");
(void)signal(SIGINT, saveint);
/* strip trailing white space */
for (cp = line + strlen(line) - 1;
cp >= line && is_WSP(*cp); cp--)
*cp = '\0';
/* skip leading white space */
cp = skip_WSP(line);
return cp;
}
#endif /* MIME_SUPPORT */
static el_mode_t
init_el_mode(
const char *el_editor,

View File

@ -1,4 +1,4 @@
/* $NetBSD: complete.h,v 1.5 2008/04/28 20:24:14 martin Exp $ */
/* $NetBSD: complete.h,v 1.6 2009/04/10 13:08:24 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -50,7 +50,6 @@ struct el_modes_s {
extern struct el_modes_s elm;
char *my_gets(el_mode_t *, const char *, char *);
char *my_getline(el_mode_t *, const char *, const char *);
void init_editline(void);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: def.h,v 1.26 2007/10/27 15:14:50 christos Exp $ */
/* $NetBSD: def.h,v 1.27 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
@ -28,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)def.h 8.4 (Berkeley) 4/20/95
* $NetBSD: def.h,v 1.26 2007/10/27 15:14:50 christos Exp $
* $NetBSD: def.h,v 1.27 2009/04/10 13:08:24 christos Exp $
*/
/*
@ -54,6 +54,7 @@
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@ -61,6 +62,8 @@
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <vis.h>
#include "pathnames.h"
#define APPEND /* New mail goes to end of mailbox */
@ -111,6 +114,7 @@
#define ENAME_METOO "metoo"
#define ENAME_NOHEADER "noheader"
#define ENAME_NOSAVE "nosave"
#define ENAME_PAGE_ALSO "page-also"
#define ENAME_PAGER "PAGER"
#define ENAME_PAGER_OFF "pager-off"
#define ENAME_PROMPT "prompt"
@ -131,7 +135,6 @@
#define ENAME_VERBOSE "verbose"
#define ENAME_VISUAL "VISUAL"
#define sizeofarray(a) (sizeof(a)/sizeof(*a))
#define equal(a, b) (strcmp(a,b)==0)/* A nice function to string compare */
struct message {
@ -249,7 +252,7 @@ struct headline {
#ifdef MIME_SUPPORT
#define GMIME 0x040 /* mime flag */
#endif
#define GMASK (GTO|GSUBJECT|GCC|GBCC|GSMOPTS)
#define GMASK (GTO | GSUBJECT | GCC | GBCC | GSMOPTS)
/* Mask of places from whence */
#define GNL 0x100 /* Print blank line after */
@ -318,14 +321,14 @@ struct attachment {
*/
struct header {
struct name *h_to; /* Dynamic "To:" string */
char *h_subject; /* Subject string */
struct name *h_cc; /* Carbon copies string */
struct name *h_bcc; /* Blind carbon copies */
struct name *h_smopts; /* Sendmail options */
char *h_in_reply_to;
struct name *h_references;
char *h_extra; /* extra lines to output */
struct name *h_to; /* Dynamic "To:" string */
char *h_subject; /* Subject string */
struct name *h_cc; /* Carbon copies string */
struct name *h_bcc; /* Blind carbon copies */
struct name *h_smopts; /* Sendmail options */
char *h_in_reply_to; /* In-Reply-To: field */
struct name *h_references; /* References: field */
struct name *h_extra; /* extra header fields */
#ifdef MIME_SUPPORT
char *h_mime_boundary; /* MIME multipart boundary string */
struct Content h_Content; /* MIME content for message */
@ -406,13 +409,6 @@ enum mailmode_e {
mm_hdrsonly /* headers only mode */
};
/*
* Kludges to handle the change from setexit / reset to setjmp / longjmp
*/
#define setexit() (void)setjmp(srbuf)
#define reset(x) longjmp(srbuf, x)
/*
* Truncate a file to the last character written. This is
* useful just before closing an old file that was opened
@ -438,7 +434,7 @@ is_WSP(int c)
return c == ' ' || c == '\t';
}
static inline char*
static inline char *
skip_WSP(const char *cp)
{
while (is_WSP(*cp))
@ -446,7 +442,7 @@ skip_WSP(const char *cp)
return __UNCONST(cp);
}
static inline char*
static inline char *
skip_space(char *p)
{
while (isspace((unsigned char)*p))
@ -454,4 +450,19 @@ skip_space(char *p)
return p;
}
/*
* strip trailing white space
*/
static inline char *
strip_WSP(char *line)
{
char *cp;
cp = line + strlen(line) - 1;
while (cp >= line && is_WSP(*cp))
cp--;
*++cp = '\0';
return cp;
}
#endif /* __DEF_H__ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: dotlock.c,v 1.9 2007/10/29 23:20:38 christos Exp $ */
/* $NetBSD: dotlock.c,v 1.10 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
@ -31,11 +31,12 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: dotlock.c,v 1.9 2007/10/29 23:20:38 christos Exp $");
__RCSID("$NetBSD: dotlock.c,v 1.10 2009/04/10 13:08:24 christos Exp $");
#endif
#include "rcv.h"
#include "extern.h"
#include "sig.h"
#ifndef O_SYNC
#define O_SYNC 0
@ -139,6 +140,7 @@ dot_lock(const char *fname, int pollinterval, FILE *fp, const char *msg)
{
char path[MAXPATHLEN];
sigset_t nset, oset;
int retval;
(void)sigemptyset(&nset);
(void)sigaddset(&nset, SIGHUP);
@ -152,17 +154,20 @@ dot_lock(const char *fname, int pollinterval, FILE *fp, const char *msg)
(void)snprintf(path, sizeof(path), "%s.lock", fname);
retval = -1;
for (;;) {
sig_check();
(void)sigprocmask(SIG_BLOCK, &nset, &oset);
if (create_exclusive(path) != -1) {
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
return 0;
retval = 0;
break;
}
else
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
if (errno != EEXIST)
return -1;
break;
if (fp && msg)
(void)fputs(msg, fp);
@ -170,11 +175,13 @@ dot_lock(const char *fname, int pollinterval, FILE *fp, const char *msg)
if (pollinterval) {
if (pollinterval == -1) {
errno = EEXIST;
return -1;
break;
}
(void)sleep((unsigned int)pollinterval);
}
}
sig_check();
return retval;
}
PUBLIC void

View File

@ -1,4 +1,4 @@
/* $NetBSD: edit.c,v 1.24 2007/10/29 23:20:38 christos Exp $ */
/* $NetBSD: edit.c,v 1.25 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,13 +34,14 @@
#if 0
static char sccsid[] = "@(#)edit.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: edit.c,v 1.24 2007/10/29 23:20:38 christos Exp $");
__RCSID("$NetBSD: edit.c,v 1.25 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
#include "rcv.h"
#include "extern.h"
#include "thread.h"
#include "sig.h"
/*
* Mail -- a mail program
@ -107,10 +108,10 @@ run_editor(FILE *fp, off_t size, int editortype, int readonlyflag)
goto out;
}
nf = NULL;
if ((editcmd =
value(editortype == 'e' ? ENAME_EDITOR : ENAME_VISUAL)) == NULL)
editcmd = value(editortype == 'e' ? ENAME_EDITOR : ENAME_VISUAL);
if (editcmd == NULL)
editcmd = editortype == 'e' ? _PATH_EX : _PATH_VI;
if (run_command(editcmd, 0, 0, -1, tempname, NULL) < 0) {
if (run_command(editcmd, NULL, 0, -1, tempname, NULL) < 0) {
(void)unlink(tempname);
goto out;
}
@ -163,14 +164,15 @@ edit1(int *msgvec, int editortype)
*/
msgCount = get_msgCount();
for (i = 0; msgvec[i] && i < msgCount; i++) {
sig_t sigint;
sigset_t oset;
struct sigaction osa;
if (i > 0) {
char buf[100];
char *p;
(void)printf("Edit message %d [ynq]? ", msgvec[i]);
if (fgets(buf, sizeof(buf), stdin) == 0)
if (fgets(buf, (int)sizeof(buf), stdin) == 0)
break;
p = skip_WSP(buf);
if (*p == 'q')
@ -180,7 +182,8 @@ edit1(int *msgvec, int editortype)
}
dot = mp = get_message(msgvec[i]);
touch(mp);
sigint = signal(SIGINT, SIG_IGN);
sig_check();
(void)sig_ignore(SIGINT, &osa, &oset);
fp = run_editor(setinput(mp), mp->m_size, editortype,
readonly);
if (fp != NULL) {
@ -213,7 +216,8 @@ edit1(int *msgvec, int editortype)
warn("/tmp");
(void)Fclose(fp);
}
(void)signal(SIGINT, sigint);
(void)sig_restore(SIGINT, &osa, &oset);
sig_check();
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.30 2007/10/27 15:14:50 christos Exp $ */
/* $NetBSD: extern.h,v 1.31 2009/04/10 13:08:24 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -29,7 +29,7 @@
* SUCH DAMAGE.
*
* @(#)extern.h 8.2 (Berkeley) 4/20/95
* $NetBSD: extern.h,v 1.30 2007/10/27 15:14:50 christos Exp $
* $NetBSD: extern.h,v 1.31 2009/04/10 13:08:24 christos Exp $
*/
#ifndef __EXTERN_H__
@ -126,6 +126,7 @@ void sort(const char **);
struct smopts_s *findsmopts(const char *, int);
int smoptscmd(void *);
int unsmoptscmd(void *);
int Header(void *);
/*
* from cmdtab.c
@ -158,10 +159,11 @@ const char *expand(const char *);
off_t fsize(FILE *);
const char *getdeadletter(void);
int getfold(char *, size_t);
void holdsigs(void);
int mail_readline(FILE *, char *, int);
#ifdef USE_EDITLINE
#define readline xreadline /* readline() is defined in libedit */
#endif
int readline(FILE *, char *, int, int);
int putline(FILE *, const char *, int);
void relsesigs(void);
int rm(char *);
FILE * setinput(const struct message *);
void setptr(FILE *, off_t);
@ -201,7 +203,7 @@ int first(int, int);
int get_Hflag(char **);
int getmsglist(char *, int *, int);
int getrawlist(const char [], char **, int);
int show_headers_and_exit(int) __attribute__((__noreturn__));
int show_headers_and_exit(int) __dead;
/*
* from main.c
@ -253,7 +255,7 @@ void flush_files(FILE *, int);
/*
* from quit.c
*/
void quit(void);
void quit(jmp_buf);
int quitcmd(void *);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: fio.c,v 1.31 2007/10/29 23:20:38 christos Exp $ */
/* $NetBSD: fio.c,v 1.32 2009/04/10 13:08:24 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,13 +34,14 @@
#if 0
static char sccsid[] = "@(#)fio.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: fio.c,v 1.31 2007/10/29 23:20:38 christos Exp $");
__RCSID("$NetBSD: fio.c,v 1.32 2009/04/10 13:08:24 christos Exp $");
#endif
#endif /* not lint */
#include "rcv.h"
#include "extern.h"
#include "thread.h"
#include "sig.h"
/*
* Mail -- a mail program
@ -215,10 +216,8 @@ setptr(FILE *ibuf, off_t offset)
for (;;) {
if (fgets(linebuf, LINESIZE, ibuf) == NULL) {
if (append(&this, mestmp)) {
warn("temporary file");
exit(1);
}
if (append(&this, mestmp))
err(EXIT_FAILURE, "temporary file");
makemessage(mestmp, omsgCount, nmsgCount);
return;
}
@ -234,18 +233,14 @@ setptr(FILE *ibuf, off_t offset)
len--;
}
(void)fwrite(linebuf, sizeof(*linebuf), len, otf);
if (ferror(otf)) {
warn("/tmp");
exit(1);
}
if (ferror(otf))
err(EXIT_FAILURE, "/tmp");
if(len)
linebuf[len - 1] = 0;
if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
nmsgCount++;
if (append(&this, mestmp)) {
warn("temporary file");
exit(1);
}
if (append(&this, mestmp))
err(EXIT_FAILURE, "temporary file");
message_init(&this, offset, MUSED|MNEW);
inhead = 1;
} else if (linebuf[0] == 0) {
@ -274,7 +269,7 @@ setptr(FILE *ibuf, off_t offset)
this.m_lines++;
if (!inhead) {
int lines_plus_wraps = 1;
size_t linelen = strlen(linebuf);
int linelen = (int)strlen(linebuf);
if (screenwidth && (int)linelen > screenwidth) {
lines_plus_wraps = linelen / screenwidth;
@ -305,7 +300,7 @@ putline(FILE *obuf, const char *linebuf, int outlf)
}
if (ferror(obuf))
return -1;
return c;
return (int)c;
}
/*
@ -314,16 +309,34 @@ putline(FILE *obuf, const char *linebuf, int outlf)
* include the newline at the end.
*/
PUBLIC int
mail_readline(FILE *ibuf, char *linebuf, int linesize)
readline(FILE *ibuf, char *linebuf, int linesize, int no_restart)
{
struct sigaction osa_sigtstp;
struct sigaction osa_sigttin;
struct sigaction osa_sigttou;
int n;
clearerr(ibuf);
sig_check();
if (no_restart) {
(void)sig_setflags(SIGTSTP, 0, &osa_sigtstp);
(void)sig_setflags(SIGTTIN, 0, &osa_sigttin);
(void)sig_setflags(SIGTTOU, 0, &osa_sigttou);
}
if (fgets(linebuf, linesize, ibuf) == NULL)
return -1;
n = strlen(linebuf);
if (n > 0 && linebuf[n - 1] == '\n')
linebuf[--n] = '\0';
n = -1;
else {
n = (int)strlen(linebuf);
if (n > 0 && linebuf[n - 1] == '\n')
linebuf[--n] = '\0';
}
if (no_restart) {
(void)sigaction(SIGTSTP, &osa_sigtstp, NULL);
(void)sigaction(SIGTTIN, &osa_sigttin, NULL);
(void)sigaction(SIGTTOU, &osa_sigttou, NULL);
}
sig_check();
return n;
}
@ -358,35 +371,6 @@ rm(char *name)
return unlink(name);
}
static int sigdepth; /* depth of holdsigs() */
static sigset_t nset, oset;
/*
* Hold signals SIGHUP, SIGINT, and SIGQUIT.
*/
PUBLIC void
holdsigs(void)
{
if (sigdepth++ == 0) {
(void)sigemptyset(&nset);
(void)sigaddset(&nset, SIGHUP);
(void)sigaddset(&nset, SIGINT);
(void)sigaddset(&nset, SIGQUIT);
(void)sigprocmask(SIG_BLOCK, &nset, &oset);
}
}
/*
* Release signals SIGHUP, SIGINT, and SIGQUIT.
*/
PUBLIC void
relsesigs(void)
{
if (--sigdepth == 0)
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
}
/*
* Determine the size of the file possessed by
* the passed buffer.
@ -434,7 +418,8 @@ expand(const char *name)
{
char xname[PATHSIZE];
char cmdbuf[PATHSIZE]; /* also used for file names */
int pid, l;
pid_t pid;
ssize_t l;
char *cp;
const char *shellcmd;
int pivec[2];
@ -481,7 +466,7 @@ expand(const char *name)
(void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
if ((shellcmd = value(ENAME_SHELL)) == NULL)
shellcmd = _PATH_CSHELL;
pid = start_command(shellcmd, 0, -1, pivec[1], "-c", cmdbuf, NULL);
pid = start_command(shellcmd, NULL, -1, pivec[1], "-c", cmdbuf, NULL);
if (pid < 0) {
(void)close(pivec[0]);
(void)close(pivec[1]);

View File

@ -1,4 +1,4 @@
/* $NetBSD: format.c,v 1.13 2008/04/28 20:24:14 martin Exp $ */
/* $NetBSD: format.c,v 1.14 2009/04/10 13:08:24 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: format.c,v 1.13 2008/04/28 20:24:14 martin Exp $");
__RCSID("$NetBSD: format.c,v 1.14 2009/04/10 13:08:24 christos Exp $");
#endif /* not __lint__ */
#include <time.h>
@ -796,7 +796,7 @@ dateof(struct tm *tm, struct message *mp, int use_hl_date)
*/
tm->tm_isdst = -1; /* let mktime(3) determine tm_isdst */
headline[0] = '\0';
(void)mail_readline(setinput(mp), headline, sizeof(headline));
(void)readline(setinput(mp), headline, (int)sizeof(headline), 0);
parse(headline, &hl, pbuf);
if (hl.l_date == NULL)
warnx("invalid headline: `%s'", headline);

View File

@ -1,4 +1,4 @@
/* $NetBSD: glob.h,v 1.11 2007/10/30 02:28:31 christos Exp $ */
/* $NetBSD: glob.h,v 1.12 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -29,7 +29,7 @@
* SUCH DAMAGE.
*
* from: @(#)glob.h 8.1 (Berkeley) 6/6/93
* $NetBSD: glob.h,v 1.11 2007/10/30 02:28:31 christos Exp $
* $NetBSD: glob.h,v 1.12 2009/04/10 13:08:25 christos Exp $
*/
/*
@ -90,8 +90,6 @@ EXTERN int wait_status; /* wait status set by wait_child() */
EXTERN int cond; /* Current state of conditional exc. */
EXTERN struct cond_stack_s *cond_stack; /* stack for if/else/endif condition */
#include <setjmp.h>
EXTERN jmp_buf srbuf;
EXTERN struct name *extra_headers; /* extra header lines */
#endif /* __GLOB_H__ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: lex.c,v 1.36 2007/12/17 22:06:00 christos Exp $ */
/* $NetBSD: lex.c,v 1.37 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,19 +34,20 @@
#if 0
static char sccsid[] = "@(#)lex.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: lex.c,v 1.36 2007/12/17 22:06:00 christos Exp $");
__RCSID("$NetBSD: lex.c,v 1.37 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
#include <assert.h>
#include <util.h>
#include "rcv.h"
#include <util.h>
#include "extern.h"
#ifdef USE_EDITLINE
#include "complete.h"
#endif
#include "format.h"
#include "sig.h"
#include "thread.h"
/*
@ -57,8 +58,88 @@ __RCSID("$NetBSD: lex.c,v 1.36 2007/12/17 22:06:00 christos Exp $");
static const char *prompt = DEFAULT_PROMPT;
static int *msgvec;
static int reset_on_stop; /* do a reset() if stopped */
static int inithdr; /* Am printing startup headers. */
static jmp_buf jmpbuf; /* The reset jmpbuf */
static int reset_on_stop; /* To do job control longjmp. */
#ifdef DEBUG_FILE_LEAK
struct glue {
struct glue *next;
int niobs;
FILE *iobs;
};
extern struct glue __sglue;
static int open_fd_cnt;
static int open_fp_cnt;
static int
file_count(void)
{
struct glue *gp;
FILE *fp;
int n;
int cnt;
cnt = 0;
for (gp = &__sglue; gp; gp = gp->next) {
for (fp = gp->iobs, n = gp->niobs; --n >= 0; fp++)
if (fp->_flags)
cnt++;
}
return cnt;
}
static int
fds_count(void)
{
int maxfd;
int cnt;
int fd;
maxfd = fcntl(0, F_MAXFD);
if (maxfd == -1) {
warn("fcntl");
return -1;
}
cnt = 0;
for (fd = 0; fd <= maxfd; fd++) {
struct stat sb;
if (fstat(fd, &sb) != -1)
cnt++;
else if (errno != EBADF
#ifdef BROKEN_CLONE_STAT /* see PRs 37878 and 37550 */
&& errno != EOPNOTSUPP
#endif
)
warn("fstat(%d): errno=%d", fd, errno);
}
return cnt;
}
static void
file_leak_init(void)
{
open_fd_cnt = fds_count();
open_fp_cnt = file_count();
}
static void
file_leak_check(void)
{
if (open_fp_cnt != file_count() ||
open_fd_cnt != fds_count()) {
(void)printf("FILE LEAK WARNING: "
"fp-count: %d (%d) "
"fd-count: %d (%d) max-fd: %d\n",
file_count(), open_fp_cnt,
fds_count(), open_fd_cnt,
fcntl(0, F_MAXFD));
}
}
#endif /* DEBUG_FILE_LEAK */
/*
* Set the size of the message vector used to construct argument
@ -129,9 +210,10 @@ setfile(const char *name)
* the message[] data structure.
*/
holdsigs();
sig_check();
sig_hold();
if (shudclob)
quit();
quit(jmpbuf);
/*
* Copy the messages into /tmp
@ -172,7 +254,8 @@ setfile(const char *name)
*/
mailsize = ftell(ibuf);
(void)Fclose(ibuf);
relsesigs();
sig_release();
sig_check();
sawcom = 0;
if (!edit && get_abs_msgCount() == 0) {
nomail:
@ -199,7 +282,8 @@ incfile(void)
ibuf = Fopen(mailname, "r");
if (ibuf == NULL)
return -1;
holdsigs();
sig_check();
sig_hold();
newsize = fsize(ibuf);
if (newsize == 0 || /* mail box is now empty??? */
newsize < mailsize) { /* mail box has shrunk??? */
@ -216,7 +300,8 @@ incfile(void)
rval = get_abs_msgCount() - omsgCount;
done:
(void)Fclose(ibuf);
relsesigs();
sig_release();
sig_check();
return rval;
}
@ -244,29 +329,6 @@ comment_char(char *line)
return NULL;
}
/*
* When we wake up after ^Z, reprint the prompt.
*/
static void
stop(int s)
{
sig_t old_action = signal(s, SIG_DFL);
sigset_t nset;
(void)sigemptyset(&nset);
(void)sigaddset(&nset, s);
(void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
(void)kill(0, s);
(void)sigprocmask(SIG_BLOCK, &nset, NULL);
(void)signal(s, old_action);
if (reset_on_stop) {
reset_on_stop = 0;
reset(0);
}
}
/*
* Signal handler is hooked by setup_piping().
* Respond to a broken pipe signal --
@ -276,9 +338,10 @@ static jmp_buf pipestop;
/*ARGSUSED*/
static void
brokpipe(int signo __unused)
lex_brokpipe(int signo)
{
longjmp(pipestop, 1);
longjmp(pipestop, signo);
}
/*
@ -331,19 +394,51 @@ shellpr(char *cp)
return NULL;
}
static int
do_paging(const char *cmd, int c_pipe)
{
char *cp, *p;
if (value(ENAME_PAGER_OFF) != NULL)
return 0;
if (c_pipe & C_PIPE_PAGER)
return 1;
if (c_pipe & C_PIPE_CRT && value(ENAME_CRT) != NULL)
return 1;
if ((cp = value(ENAME_PAGE_ALSO)) == NULL)
return 0;
if ((p = strcasestr(cp, cmd)) == NULL)
return 0;
if (p != cp && p[-1] != ',' && !is_WSP(p[-1]))
return 0;
p += strlen(cmd);
return (*p == '\0' || *p == ',' || is_WSP(*p));
}
/*
* Setup any pipe or redirection that the command line indicates.
* If none, then setup the pager unless "pager-off" is defined.
*/
static FILE *fp_stop = NULL;
static int oldfd1 = -1;
static sig_t old_sigpipe;
static int
setup_piping(char *cmdline, int c_pipe)
setup_piping(const char *cmd, char *cmdline, int c_pipe)
{
FILE *fout;
FILE *last_file;
char *cp;
sig_check();
last_file = last_registered_file(0);
fout = NULL;
@ -374,8 +469,7 @@ setup_piping(char *cmdline, int c_pipe)
}
}
else if (value(ENAME_PAGER_OFF) == NULL && (c_pipe & C_PIPE_PAGER ||
(c_pipe & C_PIPE_CRT && value(ENAME_CRT) != NULL))) {
else if (do_paging(cmd, c_pipe)) {
const char *pager;
pager = value(ENAME_PAGER);
if (pager == NULL || *pager == '\0')
@ -388,7 +482,7 @@ setup_piping(char *cmdline, int c_pipe)
}
if (fout) {
(void)signal(SIGPIPE, brokpipe);
old_sigpipe = sig_signal(SIGPIPE, lex_brokpipe);
(void)fflush(stdout);
if ((oldfd1 = dup(STDOUT_FILENO)) == -1)
err(EXIT_FAILURE, "dup failed");
@ -405,19 +499,26 @@ setup_piping(char *cmdline, int c_pipe)
static void
close_piping(void)
{
sigset_t oset;
struct sigaction osa;
if (oldfd1 != -1) {
(void)fflush(stdout);
if (fileno(stdout) != oldfd1 &&
dup2(oldfd1, STDOUT_FILENO) == -1)
err(EXIT_FAILURE, "dup2 failed");
(void)signal(SIGPIPE, SIG_IGN);
(void)sig_ignore(SIGPIPE, &osa, &oset);
close_top_files(fp_stop);
fp_stop = NULL;
(void)close(oldfd1);
oldfd1 = -1;
(void)signal(SIGPIPE, SIG_DFL);
(void)sig_signal(SIGPIPE, old_sigpipe);
(void)sig_restore(SIGPIPE, &osa, &oset);
}
sig_check();
}
/*
@ -486,6 +587,7 @@ execute(char linebuf[], enum execute_contxt_e contxt)
char *arglist[MAXARGC];
const struct cmd *com = NULL;
char *volatile cp;
int retval;
int c;
int e = 1;
@ -563,10 +665,12 @@ execute(char linebuf[], enum execute_contxt_e contxt)
}
if (!sourcing && com->c_pipe && value(ENAME_INTERACTIVE) != NULL) {
sig_check();
if (setjmp(pipestop))
goto out;
if (setup_piping(cp, com->c_pipe) == -1)
if (setup_piping(com->c_name, cp, com->c_pipe) == -1)
goto out;
}
switch (com->c_argtype & ARGTYPE_MASK) {
@ -619,8 +723,7 @@ execute(char linebuf[], enum execute_contxt_e contxt)
/*
* A vector of strings, in shell style.
*/
if ((c = getrawlist(cp, arglist,
sizeof(arglist) / sizeof(*arglist))) < 0)
if ((c = getrawlist(cp, arglist, (int)__arraycount(arglist))) < 0)
break;
if (c < com->c_minargs) {
(void)printf("%s requires at least %d arg(s)\n",
@ -654,39 +757,38 @@ out:
* Exit the current source file on
* error.
*/
retval = 0;
if (e) {
if (e < 0)
return 1;
if (loading)
return 1;
if (sourcing)
retval = 1;
else if (loading)
retval = 1;
else if (sourcing)
(void)unstack();
return 0;
}
if (com == NULL)
return 0;
if (contxt != ec_autoprint && com->c_argtype & P &&
value(ENAME_AUTOPRINT) != NULL && (dot->m_flag & MDELETED) == 0)
(void)execute(__UNCONST("print ."), ec_autoprint);
if (!sourcing && (com->c_argtype & T) == 0)
sawcom = 1;
return 0;
else if (com != NULL) {
if (contxt != ec_autoprint && com->c_argtype & P &&
value(ENAME_AUTOPRINT) != NULL &&
(dot->m_flag & MDELETED) == 0)
(void)execute(__UNCONST("print ."), ec_autoprint);
if (!sourcing && (com->c_argtype & T) == 0)
sawcom = 1;
}
sig_check();
return retval;
}
/*
* The following gets called on receipt of an interrupt. This is
* to abort printout of a command, mainly.
* Dispatching here when command() is inactive crashes rcv.
* Dispatching here when commands() is inactive crashes rcv.
* Close all open files except 0, 1, 2, and the temporary.
* Also, unstack all source files.
*/
static int inithdr; /* am printing startup headers */
/*ARGSUSED*/
static void
intr(int s __unused)
lex_intr(int signo)
{
noreset = 0;
if (!inithdr)
sawcom++;
@ -702,7 +804,7 @@ intr(int s __unused)
image = -1;
}
(void)fprintf(stderr, "Interrupt\n");
reset(0);
longjmp(jmpbuf, signo);
}
/*
@ -710,10 +812,27 @@ intr(int s __unused)
*/
/*ARGSUSED*/
static void
hangup(int s __unused)
lex_hangup(int s __unused)
{
/* nothing to do? */
exit(1);
exit(EXIT_FAILURE);
}
/*
* When we wake up after ^Z, reprint the prompt.
*
* NOTE: EditLine deals with the prompt and job control, so with it
* this does nothing, i.e., reset_on_stop == 0.
*/
static void
lex_stop(int signo)
{
if (reset_on_stop) {
reset_on_stop = 0;
longjmp(jmpbuf, signo);
}
}
/*
@ -727,18 +846,27 @@ commands(void)
char linebuf[LINESIZE];
int eofloop;
#ifdef DEBUG_FILE_LEAK
file_leak_init();
#endif
if (!sourcing) {
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
(void)signal(SIGINT, intr);
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
(void)signal(SIGHUP, hangup);
(void)signal(SIGTSTP, stop);
(void)signal(SIGTTOU, stop);
(void)signal(SIGTTIN, stop);
sig_check();
sig_hold();
(void)sig_signal(SIGINT, lex_intr);
(void)sig_signal(SIGHUP, lex_hangup);
(void)sig_signal(SIGTSTP, lex_stop);
(void)sig_signal(SIGTTOU, lex_stop);
(void)sig_signal(SIGTTIN, lex_stop);
sig_release();
}
setexit(); /* defined as (void)setjmp(srbuf) in def.h */
(void)setjmp(jmpbuf); /* "reset" location if we got an interrupt */
eofloop = 0; /* initialize this after a possible longjmp */
for (;;) {
sig_check();
(void)fflush(stdout);
sreset();
/*
@ -751,82 +879,83 @@ commands(void)
prompt = smsgprintf(prompt, dot);
if ((value(ENAME_AUTOINC) != NULL) && (incfile() > 0))
(void)printf("New mail has arrived.\n");
reset_on_stop = 1;
#ifndef USE_EDITLINE
reset_on_stop = 1; /* enable job control longjmp */
(void)printf("%s", prompt);
#endif
}
#ifdef DEBUG_FILE_LEAK
file_leak_check();
#endif
/*
* Read a line of commands from the current input
* and handle end of file specially.
*/
n = 0;
for (;;) {
sig_check();
#ifdef USE_EDITLINE
if (!sourcing) {
char *line;
if ((line = my_gets(&elm.command, prompt, NULL)) == NULL) {
line = my_gets(&elm.command, prompt, NULL);
if (line == NULL) {
if (n == 0)
n = -1;
break;
}
(void)strlcpy(linebuf, line, sizeof(linebuf));
setscreensize(); /* so we can resize a window */
}
else {
if (mail_readline(input, &linebuf[n], LINESIZE - n) < 0) {
if (readline(input, &linebuf[n], LINESIZE - n, 0) < 0) {
if (n == 0)
n = -1;
break;
}
}
#else /* USE_EDITLINE */
if (mail_readline(input, &linebuf[n], LINESIZE - n) < 0) {
if (readline(input, &linebuf[n], LINESIZE - n, reset_on_stop) < 0) {
if (n == 0)
n = -1;
break;
}
#endif /* USE_EDITLINE */
if (!sourcing)
setscreensize(); /* so we can resize window */
if (sourcing) { /* allow comments in source files */
char *ptr;
if ((ptr = comment_char(linebuf)) != NULL)
*ptr = '\0';
}
if ((n = strlen(linebuf)) == 0)
if ((n = (int)strlen(linebuf)) == 0)
break;
n--;
if (linebuf[n] != '\\')
break;
linebuf[n++] = ' ';
}
reset_on_stop = 0;
#ifndef USE_EDITLINE
sig_check();
reset_on_stop = 0; /* disable job control longjmp */
#endif
if (n < 0) {
/* eof */
char *p;
/* eof */
if (loading)
break;
if (sourcing) {
(void)unstack();
continue;
}
#ifdef USE_EDITLINE
{
char *p;
if (value(ENAME_INTERACTIVE) != NULL &&
(p = value(ENAME_IGNOREEOF)) != NULL &&
++eofloop < (*p == '\0' ? 25 : atoi(p))) {
(void)printf("Use \"quit\" to quit.\n");
continue;
}
}
#else
if (value(ENAME_INTERACTIVE) != NULL &&
value(ENAME_IGNOREEOF) != NULL &&
++eofloop < 25) {
(p = value(ENAME_IGNOREEOF)) != NULL &&
++eofloop < (*p == '\0' ? 25 : atoi(p))) {
(void)printf("Use \"quit\" to quit.\n");
continue;
}
#endif
break;
}
eofloop = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: list.c,v 1.24 2008/12/07 19:21:00 christos Exp $ */
/* $NetBSD: list.c,v 1.25 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)list.c 8.4 (Berkeley) 5/1/95";
#else
__RCSID("$NetBSD: list.c,v 1.24 2008/12/07 19:21:00 christos Exp $");
__RCSID("$NetBSD: list.c,v 1.25 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -727,7 +727,7 @@ matchfrom(int (*cmpfn)(void *, char *, size_t),
#ifdef __lint__
fieldname = fieldname;
#endif
(void)mail_readline(setinput(mp), headline, sizeof(headline));
(void)readline(setinput(mp), headline, (int)sizeof(headline), 0);
field = savestr(headline);
if (strncmp(field, "From ", 5) != 0)
return 1;
@ -1286,7 +1286,7 @@ getmsglist(char *buf, int *vector, int flags)
if (mp->m_flag & MMARK)
*ip++ = get_msgnum(mp);
*ip = 0;
return ip - vector;
return (int)(ip - vector);
}
/*
@ -1320,6 +1320,10 @@ show_headers_and_exit(int flags)
{
struct message *mp;
/* We are exiting anyway, so use the default signal handler. */
if (signal(SIGINT, SIG_DFL) == SIG_IGN)
(void)signal(SIGINT, SIG_IGN);
flags &= CMMASK;
for (mp = get_message(1); mp; mp = next_message(mp))
if (flags == 0 || !ignore_message(mp->m_flag, flags))

View File

@ -1,4 +1,4 @@
.\" $NetBSD: mail.1,v 1.55 2009/03/23 17:02:06 joerg Exp $
.\" $NetBSD: mail.1,v 1.56 2009/04/10 13:08:25 christos Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" @(#)mail.1 8.8 (Berkeley) 4/28/95
.\"
.Dd December 7, 2008
.Dd February 18, 2009
.Dt MAIL 1
.Os
.Sh NAME
@ -43,9 +43,10 @@
.Op Fl a Ar file
.Op Fl b Ar bcc-addr
.Op Fl c Ar cc-addr
.Op Fl r Ar rcfile
.Op Fl s Ar subject
.Ar to-addr ...
.Op Ar sendmail-flags
.Op - Ar sendmail-flags
.Nm
.Op Fl EIiNnv
.Op Fl H Ns Op colon-modifier
@ -118,6 +119,13 @@ when reading mail or editing a mail folder.
Inhibits reading
.Pa /etc/mail.rc
upon startup.
.It Fl r
Specify an alternate user rcfile to load.
This overrides the value specified in the environment variable
.Ev MAILRC
which in turn overrides the default
.Pa ~/.mailrc
file.
.It Fl s
Specify subject on command line
(only the first argument after the
@ -499,6 +507,33 @@ but also saves MIME parts that don't have a filename associated with
them.
For the unnamed parts, a filename is suggested containing the message
and part numbers, and the subtype.
.It Ic Header
.Pq Ic H
Specify or show additional header fields.
This is intended for adding extra header fields like
.Dq Reply-To:
or
.Dq X-Organization:
to the header.
For example:
.Bd -literal -offset 0
Header X-Mailer: NetBSD mail(1) 9.1
.Ed
.Pp
would add the
.Dq X-Mailer: NetBSD mail(1) 9.1
line to the message header.
Without any arguments, the extra header fields are displayed.
With only a header name (including the
.Sq \&: ) ,
it will delete all extra header fields with that name.
Note: Although some syntax checking is done on the header line, care
should be taken to ensure that it complies with RFC 2821 and 2822.
Also, the extra header lines are not currently displayed by the
.Ic \&~h
tilde command when sending mail (use
.Ic \&~:Header
to see them).
.It Ic More
.Pq Ic M
Like
@ -1292,7 +1327,7 @@ Message headers currently being ignored (by the
or
.Ic retain
command) are not included.
.It Ic \&~F Ns Ar messages
.It Ic \&~
Identical to
.Ic \&~f ,
except all message headers are included.
@ -1428,6 +1463,8 @@ and
.Ic Type
commands.
Normally these commands do not invoke the pager.
(See
.Va page-also . )
.It Ar debug
Setting the binary option
.Ar debug
@ -1572,6 +1609,17 @@ in your home directory.
Setting the binary option
.Ar nosave
prevents this.
.It Ar page-also
A comma or whitespace delimited list of additional commands to page.
The comparisons are case insensitive, so if
.Ic view
is in the list, both
.Ic view
and
.Ic View
will page.
.It Ar pager-off
If set, disable the pager on all commands.
.It Ar quiet
Suppresses the printing of the version when first invoked.
.It Ar recursive-commands

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.29 2008/07/21 14:19:24 lukem Exp $ */
/* $NetBSD: main.c,v 1.30 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/20/95";
#else
__RCSID("$NetBSD: main.c,v 1.29 2008/07/21 14:19:24 lukem Exp $");
__RCSID("$NetBSD: main.c,v 1.30 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -50,6 +50,7 @@ __RCSID("$NetBSD: main.c,v 1.29 2008/07/21 14:19:24 lukem Exp $");
#include <util.h>
#include "extern.h"
#include "sig.h"
#ifdef USE_EDITLINE
#include "complete.h"
@ -68,19 +69,26 @@ __RCSID("$NetBSD: main.c,v 1.29 2008/07/21 14:19:24 lukem Exp $");
* Startup -- interface with user.
*/
static jmp_buf hdrjmp;
/*
* Interrupt printing of the headers.
*/
/*ARGSUSED*/
__dead
static void
hdrstop(int signo __unused)
usage(void)
{
(void)fflush(stdout);
(void)fprintf(stderr, "\nInterrupt\n");
longjmp(hdrjmp, 1);
#ifdef MIME_SUPPORT
(void)fputs("\
Usage: mail [-EiInv] [-r rcfile] [-s subject] [-a file] [-c cc-addr]\n\
[-b bcc-addr] to-addr ... [- sendmail-options ...]\n\
mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
stderr);
#else /* MIME_SUPPORT */
(void)fputs("\
Usage: mail [-EiInv] [-r rcfile] [-s subject] [-c cc-addr] [-b bcc-addr]\n\
to-addr ... [- sendmail-options ...]\n\
mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
stderr);
#endif /* MIME_SUPPORT */
exit(1);
}
/*
@ -168,7 +176,8 @@ lexpand(char *str, int ntype)
PUBLIC int
main(int argc, char *argv[])
{
int i;
jmp_buf jmpbuf;
struct sigaction sa;
struct name *to, *cc, *bcc, *smopts;
#ifdef MIME_SUPPORT
struct name *attach_optargs;
@ -177,9 +186,9 @@ main(int argc, char *argv[])
char *subject;
const char *ef;
char nosrc = 0;
sig_t prevint;
const char *rc;
int volatile Hflag;
int Hflag;
int i;
/*
* For portability, call setprogname() early, before
@ -191,11 +200,17 @@ main(int argc, char *argv[])
* Set up a reasonable environment.
* Figure out whether we are being run interactively,
* start the SIGCHLD catcher, and so forth.
* (Other signals are setup later by sig_setup().)
*/
(void)signal(SIGCHLD, sigchild);
(void)sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sigchild;
(void)sigaction(SIGCHLD, &sa, NULL);
if (isatty(0))
assign(ENAME_INTERACTIVE, "");
image = -1;
/*
* Now, determine how we are being used.
* We successively pick off - flags.
@ -203,6 +218,7 @@ main(int argc, char *argv[])
* of users to mail to. Argp will be set to point to the
* first of these users.
*/
rc = NULL;
ef = NULL;
to = NULL;
cc = NULL;
@ -213,9 +229,9 @@ main(int argc, char *argv[])
#ifdef MIME_SUPPORT
attach_optargs = NULL;
attach_end = NULL;
while ((i = getopt(argc, argv, ":~EH:INT:a:b:c:dfins:u:v")) != -1)
while ((i = getopt(argc, argv, ":~EH:INT:a:b:c:dfinr:s:u:v")) != -1)
#else
while ((i = getopt(argc, argv, ":~EH:INT:b:c:dfins:u:v")) != -1)
while ((i = getopt(argc, argv, ":~EH:INT:b:c:dfinr:s:u:v")) != -1)
#endif
{
switch (i) {
@ -262,6 +278,9 @@ main(int argc, char *argv[])
case 'd':
debug++;
break;
case 'r':
rc = optarg;
break;
case 's':
/*
* Give a subject field for sending from
@ -356,23 +375,8 @@ main(int argc, char *argv[])
(void)fprintf(stderr,
"%s: unknown option -- %c\n", getprogname(),
optopt);
#ifdef MIME_SUPPORT
(void)fputs("\
Usage: mail [-EiInv] [-s subject] [-a file] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
[- sendmail-options ...]\n\
mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
stderr);
#else /* MIME_SUPPORT */
(void)fputs("\
Usage: mail [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
[- sendmail-options ...]\n\
mail [-EiInNv] [-H[colon-modifier]] -f [name]\n\
mail [-EiInNv] [-H[colon-modifier]] [-u user]\n",
stderr);
#endif /* MIME_SUPPORT */
exit(1);
usage(); /* print usage message and die */
/*NOTREACHED*/
}
}
for (i = optind; (argv[i]) && (*argv[i] != '-'); i++)
@ -405,7 +409,7 @@ Usage: mail [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
* Expand returns a savestr, but load only uses the file name
* for fopen, so it's safe to do this.
*/
if ((rc = getenv("MAILRC")) == 0)
if (rc == NULL && (rc = getenv("MAILRC")) == NULL)
rc = "~/.mailrc";
load(expand(rc));
setscreensize(); /* do this after loading the rcfile */
@ -420,6 +424,8 @@ Usage: mail [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
init_editline();
#endif
sig_setup();
switch (mailmode) {
case mm_sending:
(void)mail(to, cc, bcc, smopts, subject,
@ -441,23 +447,25 @@ Usage: mail [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
ef = "%";
if (setfile(ef) < 0)
exit(1); /* error already reported */
if (setjmp(hdrjmp) == 0) {
if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
(void)signal(SIGINT, hdrstop);
if (value(ENAME_QUIET) == NULL)
(void)printf("Mail version %s. Type ? for help.\n",
version);
if (mailmode == mm_hdrsonly)
show_headers_and_exit(Hflag); /* NORETURN */
announce();
(void)fflush(stdout);
(void)signal(SIGINT, prevint);
if (value(ENAME_QUIET) == NULL)
(void)printf("Mail version %s. Type ? for help.\n",
version);
if (mailmode == mm_hdrsonly)
show_headers_and_exit(Hflag); /* NORETURN */
announce();
(void)fflush(stdout);
if (setjmp(jmpbuf) != 0) {
/* Return here if quit() fails below. */
(void)printf("Use 'exit' to quit without saving changes.\n");
}
commands();
/* Ignore these signals from now on! */
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
quit();
quit(jmpbuf);
break;
default:

View File

@ -1,4 +1,4 @@
/* $NetBSD: mime_attach.c,v 1.11 2009/03/11 01:10:05 christos Exp $ */
/* $NetBSD: mime_attach.c,v 1.12 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: mime_attach.c,v 1.11 2009/03/11 01:10:05 christos Exp $");
__RCSID("$NetBSD: mime_attach.c,v 1.12 2009/04/10 13:08:25 christos Exp $");
#endif /* not __lint__ */
#include <assert.h>
@ -41,7 +41,6 @@ __RCSID("$NetBSD: mime_attach.c,v 1.11 2009/03/11 01:10:05 christos Exp $");
#include <fcntl.h>
#include <libgen.h>
#include <magic.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@ -60,6 +59,7 @@ __RCSID("$NetBSD: mime_attach.c,v 1.11 2009/03/11 01:10:05 christos Exp $");
#include "mime_child.h"
#endif
#include "glob.h"
#include "sig.h"
#if 0
/*
@ -373,7 +373,7 @@ content_type_by_name(char *filename)
}
cp = magic_file(magic, filename);
if (cp == NULL) {
warnx("magic_file: %s", magic_error(magic));
warnx("magic_load: %s", magic_error(magic));
return NULL;
}
if (filename &&
@ -787,9 +787,15 @@ get_line(el_mode_t *em, const char *pr, const char *str, int i)
* seems to handle it badly.
*/
(void)easprintf(&prompt, "#%-7d %s: ", i, pr);
line = my_getline(em, prompt, __UNCONST(str));
/* LINTED */
line = line ? savestr(line) : __UNCONST("");
line = my_gets(em, prompt, __UNCONST(str));
if (line != NULL) {
(void)strip_WSP(line); /* strip trailing whitespace */
line = skip_WSP(line); /* skip leading white space */
line = savestr(line); /* XXX - do we need this? */
}
else {
line = __UNCONST("");
}
free(prompt);
return line;
@ -800,8 +806,8 @@ sget_line(el_mode_t *em, const char *pr, const char **str, int i)
{
char *line;
line = get_line(em, pr, *str, i);
if (strcmp(line, *str) != 0)
*str = savestr(line);
if (line != NULL && strcmp(line, *str) != 0)
*str = line;
}
static void
@ -949,14 +955,14 @@ edit_attachlist(struct attachment *alist)
* Hook used by the '~@' escape to attach files.
*/
PUBLIC struct attachment*
mime_attach_files(struct attachment *attach, char *linebuf)
mime_attach_files(struct attachment * volatile attach, char *linebuf)
{
struct attachment *ap;
char *argv[MAXARGC];
int argc;
int attach_num;
argc = getrawlist(linebuf, argv, sizeofarray(argv));
argc = getrawlist(linebuf, argv, (int)__arraycount(argv));
attach_num = 1;
for (ap = attach; ap && ap->a_flink; ap = ap->a_flink)
attach_num++;
@ -1004,7 +1010,8 @@ mime_attach_optargs(struct name *optargs)
int i;
if (expand_optargs != NULL)
argc = getrawlist(np->n_name, argv, sizeofarray(argv));
argc = getrawlist(np->n_name,
argv, (int)__arraycount(argv));
else {
if (np->n_name == '\0')
argc = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mime_codecs.c,v 1.8 2009/01/18 01:29:57 lukem Exp $ */
/* $NetBSD: mime_codecs.c,v 1.9 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -52,7 +52,7 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: mime_codecs.c,v 1.8 2009/01/18 01:29:57 lukem Exp $");
__RCSID("$NetBSD: mime_codecs.c,v 1.9 2009/04/10 13:08:25 christos Exp $");
#endif /* not __lint__ */
#include <assert.h>
@ -276,7 +276,7 @@ mime_bintob64(char *b64, const char *bin, size_t cnt)
static const char b64table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const unsigned char *p = (const unsigned char*)bin;
int i;
ssize_t i;
for (i = cnt; i > 0; i -= 3) {
unsigned a = p[0];
@ -314,7 +314,7 @@ mime_fB64_encode(FILE *fi, FILE *fo, void *cookie __unused)
{
static char b64[MIME_BASE64_LINE_MAX];
static char mem[3 * (MIME_BASE64_LINE_MAX / 4)];
int cnt;
size_t cnt;
char *cp;
size_t limit;
#ifdef __lint__
@ -530,9 +530,9 @@ mime_fQP_decode(FILE *fi, FILE *fo, void *cookie __unused)
cookie = cookie;
#endif
while ((line = fgetln(fi, &len)) != NULL) {
int c;
char *p;
char *end;
end = line + len;
for (p = line; p < end; p++) {
if (*p == '=') {
@ -540,11 +540,13 @@ mime_fQP_decode(FILE *fi, FILE *fo, void *cookie __unused)
while (p < end && is_WSP(*p))
p++;
if (*p != '\n' && p + 1 < end) {
int c;
char buf[3];
buf[0] = *p++;
buf[1] = *p;
buf[2] = '\0';
c = strtol(buf, NULL, 16);
c = (int)strtol(buf, NULL, 16);
(void)fputc(c, fo);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mime_decode.c,v 1.14 2009/01/18 01:29:57 lukem Exp $ */
/* $NetBSD: mime_decode.c,v 1.15 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -34,14 +34,13 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: mime_decode.c,v 1.14 2009/01/18 01:29:57 lukem Exp $");
__RCSID("$NetBSD: mime_decode.c,v 1.15 2009/04/10 13:08:25 christos Exp $");
#endif /* not __lint__ */
#include <assert.h>
#include <err.h>
#include <fcntl.h>
#include <libgen.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,4 +1,4 @@
/* $NetBSD: mime_detach.c,v 1.3 2008/04/28 20:24:14 martin Exp $ */
/* $NetBSD: mime_detach.c,v 1.4 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: mime_detach.c,v 1.3 2008/04/28 20:24:14 martin Exp $");
__RCSID("$NetBSD: mime_detach.c,v 1.4 2009/04/10 13:08:25 christos Exp $");
#endif /* not __lint__ */
#include <assert.h>
@ -54,6 +54,7 @@ __RCSID("$NetBSD: mime_detach.c,v 1.3 2008/04/28 20:24:14 martin Exp $");
#include "mime_codecs.h"
#include "mime_detach.h"
#endif
#include "sig.h"
static struct {
@ -95,8 +96,12 @@ detach_get_fname(char *prompt, char *pathname)
{
if (!detach_ctl.batch) {
char *fname;
fname = my_gets(&elm.filec, prompt, pathname);
fname = skip_WSP(fname); /* XXX - do this? */
if (fname == NULL) /* ignore this attachment */
return NULL;
(void)strip_WSP(fname);
fname = skip_WSP(fname);
if (*fname == '\0') /* ignore this attachment */
return NULL;
pathname = savestr(fname); /* save this or it gets trashed */
@ -130,7 +135,12 @@ detach_open_core(char *fname, const char *partstr)
(void)sasprintf(&p, "%-7s overwrite: Always/Never/once/next/rename (ANonr)[n]? ",
partstr, fname);
p = my_gets(&elm.string, p, NULL);
if (p == NULL)
goto start;
(void)strip_WSP(p);
p = skip_WSP(p);
switch (*p) {
case 'A': detach_ctl.overwrite = 1;
detach_ctl.batch = 1;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mime_header.c,v 1.7 2009/01/18 01:29:57 lukem Exp $ */
/* $NetBSD: mime_header.c,v 1.8 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -39,9 +39,10 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: mime_header.c,v 1.7 2009/01/18 01:29:57 lukem Exp $");
__RCSID("$NetBSD: mime_header.c,v 1.8 2009/04/10 13:08:25 christos Exp $");
#endif /* not __lint__ */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -91,16 +92,17 @@ mime_QPh_decode(char *outbuf, size_t outlen, const char *inbuf, size_t inlen)
if (*p == '=') {
p++;
if (p + 1 < inend) {
int c;
size_t c;
char *bufend;
char buf[3];
buf[0] = *p++;
buf[1] = *p;
buf[2] = '\0';
c = strtol(buf, &bufend, 16);
if (bufend != &buf[2])
return -1;
*q++ = c;
*q++ = (char)c;
}
else
return -1;
@ -181,8 +183,11 @@ decode_word(const char **ibuf, char **obuf, char *oend, const char *to_cs)
if (iend > *ibuf + 75)
return -1;
if (oend < *obuf + 1) {
assert(/*CONSTCOND*/ 0); /* We have a coding error! */
return -1;
}
dstend = to_cs ? decword : *obuf;
/* XXX: what if oend <= *obuf, or decword == "" ? */
dstlen = (to_cs ? sizeof(decword) : (size_t)(oend - *obuf)) - 1;
if (enctype == 'B' || enctype == 'b')

View File

@ -1,4 +1,4 @@
/* $NetBSD: popen.c,v 1.24 2007/10/30 02:28:31 christos Exp $ */
/* $NetBSD: popen.c,v 1.25 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: popen.c,v 1.24 2007/10/30 02:28:31 christos Exp $");
__RCSID("$NetBSD: popen.c,v 1.25 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -46,6 +46,7 @@ __RCSID("$NetBSD: popen.c,v 1.24 2007/10/30 02:28:31 christos Exp $");
#include "rcv.h"
#include "extern.h"
#include "sig.h"
#define READ 0
#define WRITE 1
@ -146,6 +147,10 @@ Fdopen(int fd, const char *mode)
PUBLIC int
Fclose(FILE *fp)
{
if (fp == NULL)
return 0;
unregister_file(fp);
return fclose(fp);
}
@ -169,17 +174,17 @@ prepare_child(sigset_t *nset, int infd, int outfd)
}
if (outfd >= 0 && outfd != 1)
(void)dup2(outfd, 1);
if (nset == NULL)
return;
if (nset != NULL) {
for (i = 1; i < NSIG; i++)
for (i = 1; i < NSIG; i++) {
if (sigismember(nset, i))
(void)signal(i, SIG_IGN);
}
if (!sigismember(nset, SIGINT))
(void)signal(SIGINT, SIG_DFL);
(void)sigemptyset(&eset);
(void)sigprocmask(SIG_SETMASK, &eset, NULL);
}
if (nset == NULL || !sigismember(nset, SIGINT))
(void)signal(SIGINT, SIG_DFL);
(void)sigemptyset(&eset);
(void)sigprocmask(SIG_SETMASK, &eset, NULL);
}
/*
@ -196,15 +201,18 @@ start_commandv(const char *cmd, sigset_t *nset, int infd, int outfd,
{
pid_t pid;
sig_check();
if ((pid = fork()) < 0) {
warn("fork");
return -1;
}
if (pid == 0) {
char *argv[100];
int i = getrawlist(cmd, argv, sizeof(argv)/ sizeof(*argv));
size_t i;
while ((argv[i++] = va_arg(args, char *)) != NULL)
i = getrawlist(cmd, argv, (int)__arraycount(argv));
while (i < __arraycount(argv) - 1 &&
(argv[i++] = va_arg(args, char *)) != NULL)
continue;
argv[i] = NULL;
prepare_child(nset, infd, outfd);
@ -350,6 +358,9 @@ Pclose(FILE *ptr)
int i;
sigset_t nset, oset;
if (ptr == NULL)
return 0;
i = file_pid(ptr);
unregister_file(ptr);
(void)fclose(ptr);
@ -429,13 +440,48 @@ run_command(const char *cmd, sigset_t *nset, int infd, int outfd, ...)
{
pid_t pid;
va_list args;
int rval;
#ifdef BROKEN_EXEC_TTY_RESTORE
struct termios ttybuf;
int tcrval;
/*
* XXX - grab the tty settings as currently they can get
* trashed by emacs-21 when suspending with bash-3.2.25 as the
* shell.
*
* 1) from the mail editor, start "emacs -nw" (21.4)
* 2) suspend emacs to the shell (bash 3.2.25)
* 3) resume emacs
* 4) exit emacs back to the mail editor
* 5) discover the tty is screwed: the mail editor is no
* longer receiving characters
*
* - This occurs on both i386 and amd64.
* - This did _NOT_ occur before 4.99.10.
* - This does _NOT_ occur if the editor is vi(1) or if the shell
* is /bin/sh.
* - This _DOES_ happen with the old mail(1) from 2006-01-01 (long
* before my changes).
*
* This is the commit that introduced this "feature":
* http://mail-index.netbsd.org/source-changes/2007/02/09/0020.html
*/
if ((tcrval = tcgetattr(fileno(stdin), &ttybuf)) == -1)
warn("tcgetattr");
#endif
va_start(args, outfd);
pid = start_commandv(cmd, nset, infd, outfd, args);
va_end(args);
if (pid < 0)
return -1;
return wait_command(pid);
rval = wait_command(pid);
#ifdef BROKEN_EXEC_TTY_RESTORE
if (tcrval != -1 && tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf) == -1)
warn("tcsetattr");
#endif
return rval;
}
/*ARGSUSED*/
@ -445,15 +491,15 @@ sigchild(int signo __unused)
pid_t pid;
int status;
struct child *cp;
int save_errno = errno;
int save_errno;
while ((pid =
waitpid((pid_t)-1, &status, WNOHANG)) > 0) {
cp = findchild(pid, 1);
save_errno = errno;
while ((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0) {
cp = findchild(pid, 1); /* async-signal-safe: we don't alloc */
if (!cp)
continue;
if (cp->free)
delchild(cp);
delchild(cp); /* async-signal-safe: list changes */
else {
cp->done = 1;
cp->status = status;

View File

@ -1,4 +1,4 @@
/* $NetBSD: quit.c,v 1.26 2006/11/28 18:45:32 christos Exp $ */
/* $NetBSD: quit.c,v 1.27 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,13 +34,14 @@
#if 0
static char sccsid[] = "@(#)quit.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: quit.c,v 1.26 2006/11/28 18:45:32 christos Exp $");
__RCSID("$NetBSD: quit.c,v 1.27 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
#include "rcv.h"
#include "extern.h"
#include "thread.h"
#include "sig.h"
/*
* Rcv -- receive mail rationally.
@ -132,18 +133,22 @@ writeback(FILE *res)
* file from the temporary. Save any new stuff appended to the file.
*/
static void
edstop(void)
edstop(jmp_buf jmpbuf)
{
int gotcha, c;
struct message *mp;
FILE *obuf, *ibuf, *readstat = NULL;
FILE *obuf;
FILE *ibuf;
FILE *readstat;
struct stat statb;
char tempname[PATHSIZE];
int fd;
sig_check();
if (readonly)
return;
holdsigs();
readstat = NULL;
if (Tflag != NULL) {
if ((readstat = Fopen(Tflag, "w")) == NULL)
Tflag = NULL;
@ -175,15 +180,15 @@ edstop(void)
warn("%s", tempname);
if (fd != -1)
(void)close(fd);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -11);
}
if ((ibuf = Fopen(mailname, "r")) == NULL) {
warn("%s", mailname);
(void)Fclose(obuf);
(void)rm(tempname);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -1);
}
(void)fseek(ibuf, (long)mailsize, 0);
while ((c = getc(ibuf)) != EOF)
@ -194,16 +199,16 @@ edstop(void)
(void)Fclose(obuf);
(void)Fclose(ibuf);
(void)rm(tempname);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -1);
}
(void)Fclose(ibuf);
(void)Fclose(obuf);
if ((ibuf = Fopen(tempname, "r")) == NULL) {
warn("%s", tempname);
(void)rm(tempname);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -1);
}
(void)rm(tempname);
}
@ -211,8 +216,8 @@ edstop(void)
(void)fflush(stdout);
if ((obuf = Fopen(mailname, "r+")) == NULL) {
warn("%s", mailname);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -1);
}
trunc(obuf);
c = 0;
@ -222,8 +227,8 @@ edstop(void)
c++;
if (sendmessage(mp, obuf, NULL, NULL, NULL) < 0) {
warn("%s", mailname);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -1);
}
}
gotcha = (c == 0 && ibuf == NULL);
@ -235,8 +240,8 @@ edstop(void)
(void)fflush(obuf);
if (ferror(obuf)) {
warn("%s", mailname);
relsesigs();
reset(0);
sig_release();
longjmp(jmpbuf, -1);
}
(void)Fclose(obuf);
if (gotcha) {
@ -247,7 +252,8 @@ edstop(void)
(void)fflush(stdout);
done:
relsesigs();
sig_release();
sig_check();
}
/*
@ -256,20 +262,21 @@ done:
* Remove the system mailbox, if none saved there.
*/
PUBLIC void
quit(void)
quit(jmp_buf jmpbuf)
{
int mcount, p, modify, autohold, anystat, holdbit, nohold;
FILE *ibuf = NULL, *obuf, *fbuf, *rbuf, *readstat = NULL, *abuf;
_Bool append;
FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
struct message *mp;
int c, fd;
struct stat minfo;
const char *mbox;
char tempname[PATHSIZE];
#ifdef __GNUC__
obuf = NULL; /* XXX gcc -Wuninitialized */
#ifdef __GNUC__ /* XXX gcc -Wuninitialized */
ibuf = NULL;
readstat = NULL;
#endif
/*
* If we are read only, we can't do anything,
* so just return quickly.
@ -286,7 +293,7 @@ quit(void)
* in edstop()
*/
if (edit) {
edstop();
edstop(jmpbuf);
return;
}
@ -418,7 +425,8 @@ nolock:
mbox = expand("&");
mcount = c;
if (value(ENAME_APPEND) == NULL) {
append = value(ENAME_APPEND) != NULL;
if (!append) {
(void)snprintf(tempname, sizeof(tempname),
"%s/mail.RmXXXXXXXXXX", tmpdir);
if ((fd = mkstemp(tempname)) == -1 ||
@ -476,7 +484,8 @@ nolock:
if (mp->m_flag & MBOX)
if (sendmessage(mp, obuf, saveignore, NULL, NULL) < 0) {
warn("%s", mbox);
(void)Fclose(ibuf);
if (!append)
(void)Fclose(ibuf);
(void)Fclose(obuf);
(void)Fclose(fbuf);
dot_unlock(mailname);
@ -489,7 +498,7 @@ nolock:
* If we are appending, this is unnecessary.
*/
if (value(ENAME_APPEND) == NULL) {
if (!append) {
rewind(ibuf);
c = getc(ibuf);
while (c != EOF) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: send.c,v 1.33 2009/01/25 14:07:18 lukem Exp $ */
/* $NetBSD: send.c,v 1.34 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,16 +34,18 @@
#if 0
static char sccsid[] = "@(#)send.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: send.c,v 1.33 2009/01/25 14:07:18 lukem Exp $");
__RCSID("$NetBSD: send.c,v 1.34 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
#include <assert.h>
#include "rcv.h"
#include "extern.h"
#ifdef MIME_SUPPORT
#include "mime.h"
#endif
#include "sig.h"
/*
* Mail -- a mail program
@ -125,9 +127,11 @@ sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
char *cp;
size_t prefixlen;
size_t linelen;
int rval;
ignoring = 0;
prefixlen = 0;
rval = -1;
/*
* Compute the prefix string, without trailing whitespace
@ -145,6 +149,8 @@ sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
dostat = doign == 0 || !isign("status", doign);
infld = 0;
firstline = 1;
sig_check();
/*
* Process headers first
*/
@ -153,7 +159,8 @@ sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
obuf = mime_decode_header(mip);
#endif
while (len > 0 && isheadflag) {
if (fgets(line, sizeof(line), ibuf) == NULL)
sig_check();
if (fgets(line, (int)sizeof(line), ibuf) == NULL)
break;
len -= linelen = strlen(line);
if (firstline) {
@ -254,26 +261,32 @@ sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
}
(void)fwrite(line, sizeof(*line), linelen, obuf);
if (ferror(obuf))
return -1;
goto out;
}
}
sig_check();
/*
* Copy out message body
*/
#ifdef MIME_SUPPORT
if (mip) {
obuf = mime_decode_body(mip);
if (obuf == NULL) /* XXX - early out */
return 0;
sig_check();
if (obuf == NULL) { /* XXX - early out */
rval = 0;
goto out;
}
}
#endif
if (doign == ignoreall)
len--; /* skip final blank line */
linelen = 0; /* needed for in case len == 0 */
if (prefix != NULL)
if (prefix != NULL) {
while (len > 0) {
if (fgets(line, sizeof(line), ibuf) == NULL) {
sig_check();
if (fgets(line, (int)sizeof(line), ibuf) == NULL) {
linelen = 0;
break;
}
@ -289,24 +302,33 @@ sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
prefixlen, obuf);
(void)fwrite(line, sizeof(*line), linelen, obuf);
if (ferror(obuf))
return -1;
goto out;
}
else
}
else {
while (len > 0) {
sig_check();
linelen = (size_t)len < sizeof(line) ? (size_t)len : sizeof(line);
if ((linelen = fread(line, sizeof(*line), linelen, ibuf)) == 0)
if ((linelen = fread(line, sizeof(*line), linelen, ibuf)) == 0) {
break;
}
len -= linelen;
if (fwrite(line, sizeof(*line), linelen, obuf) != linelen)
return -1;
goto out;
}
}
sig_check();
if (doign == ignoreall && linelen > 0 && line[linelen - 1] != '\n') {
int c;
/* no final blank line */
if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF)
return -1;
goto out;
}
return 0;
rval = 0;
out:
sig_check();
return rval;
}
/*
@ -340,9 +362,10 @@ fixhead(struct header *hp, struct name *tolist)
* Format the given header line to not exceed 72 characters.
*/
static void
fmt(const char *str, struct name *np, FILE *fo, int comma)
fmt(const char *str, struct name *np, FILE *fo, size_t comma)
{
int col, len;
size_t col;
size_t len;
comma = comma ? 1 : 0;
col = strlen(str);
@ -366,6 +389,51 @@ fmt(const char *str, struct name *np, FILE *fo, int comma)
(void)putc('\n', fo);
}
/*
* Formatting for extra_header lines: try to wrap them before 72
* characters.
*
* XXX - should this allow for quoting?
*/
static void
fmt2(const char *str, FILE *fo)
{
const char *p;
size_t col;
col = 0;
p = strchr(str, ':');
assert(p != NULL); /* this is a coding error */
while (str <= p) { /* output the header name */
(void)putc(*str, fo);
str++;
col++;
}
assert(is_WSP(*str)); /* this is a coding error */
(void)putc(' ', fo); /* output a single space after the ':' */
str = skip_WSP(str);
while (*str != '\0') {
if (p <= str) {
p = strpbrk(str, " \t");
if (p == NULL)
p = str + strlen(str);
if (col + (p - str) > 72 && col > 4) {
(void)fputs("\n ", fo);
col = 4;
str = skip_WSP(str);
continue;
}
}
(void)putc(*str, fo);
str++;
col++;
}
(void)putc('\n', fo);
}
/*
* Dump the to, subject, cc header on the
* passed file buffer.
@ -373,23 +441,29 @@ fmt(const char *str, struct name *np, FILE *fo, int comma)
PUBLIC int
puthead(struct header *hp, FILE *fo, int w)
{
struct name *np;
int gotcha;
gotcha = 0;
if (hp->h_to != NULL && w & GTO)
fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
fmt("To:", hp->h_to, fo, w & GCOMMA), gotcha++;
if (hp->h_subject != NULL && w & GSUBJECT)
(void)fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
if (hp->h_smopts != NULL && w & GSMOPTS)
(void)fprintf(fo, "(sendmail options: %s)\n", detract(hp->h_smopts, GSMOPTS)), gotcha++;
if (hp->h_cc != NULL && w & GCC)
fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++;
fmt("Cc:", hp->h_cc, fo, w & GCOMMA), gotcha++;
if (hp->h_bcc != NULL && w & GBCC)
fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++;
fmt("Bcc:", hp->h_bcc, fo, w & GCOMMA), gotcha++;
if (hp->h_in_reply_to != NULL && w & GMISC)
(void)fprintf(fo, "In-Reply-To: %s\n", hp->h_in_reply_to), gotcha++;
if (hp->h_references != NULL && w & GMISC)
fmt("References:", hp->h_references, fo, w&GCOMMA), gotcha++;
fmt("References:", hp->h_references, fo, w & GCOMMA), gotcha++;
if (hp->h_extra != NULL && w & GMISC) {
for (np = hp->h_extra; np != NULL; np = np->n_flink)
fmt2(np->n_name, fo);
gotcha++;
}
if (hp->h_smopts != NULL && w & GSMOPTS)
(void)fprintf(fo, "(sendmail options: %s)\n", detract(hp->h_smopts, GSMOPTS)), gotcha++;
#ifdef MIME_SUPPORT
if (w & GMIME && (hp->h_attach || value(ENAME_MIME_ENCODE_MSG)))
mime_putheader(fo, hp), gotcha++;
@ -426,11 +500,12 @@ infix(struct header *hp, FILE *fi)
return fi;
}
(void)rm(tempname);
(void)puthead(hp, nfo,
GTO | GSUBJECT | GCC | GBCC | GMISC | GNL | GCOMMA
#ifdef MIME_SUPPORT
(void)puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GMISC|GMIME|GNL|GCOMMA);
#else
(void)puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GMISC|GNL|GCOMMA);
| GMIME
#endif
);
c = getc(fi);
while (c != EOF) {
@ -576,6 +651,28 @@ mail2(FILE *mtf, const char **namelist)
}
}
static struct name *
ncopy(struct name *np)
{
struct name *rv;
struct name *lp;
struct name *tp;
rv = NULL;
for (/*EMPTY*/; np; np = np->n_flink) {
tp = nalloc(np->n_name, np->n_type);
if (rv == NULL)
rv = tp;
else {
/*LINTED*/
lp->n_flink = tp;
tp->n_blink = lp;
}
lp = tp;
}
return rv;
}
/*
* Mail a message on standard input to the people indicated
* in the passed header. (Internal interface).
@ -594,6 +691,12 @@ mail1(struct header *hp, int printheaders)
if ((mtf = collect(hp, printheaders)) == NULL)
return;
/*
* Grab any extra header lines. Do this after collect() so
* that we can add header lines while collecting.
*/
hp->h_extra = ncopy(extra_headers);
if (value(ENAME_INTERACTIVE) != NULL) {
if (value(ENAME_ASKCC) != NULL || value(ENAME_ASKBCC) != NULL) {
if (value(ENAME_ASKCC) != NULL)

424
usr.bin/mail/sig.c Normal file
View File

@ -0,0 +1,424 @@
/* $NetBSD: sig.c,v 1.1 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: sig.c,v 1.1 2009/04/10 13:08:25 christos Exp $");
#endif /* not lint */
#include <assert.h>
#include <util.h>
#include <sys/queue.h>
#include "rcv.h"
#include "extern.h"
#include "sig.h"
/*
* Mail -- a mail program
*
* Signal routines.
*/
static sig_t sigarray[NSIG];
typedef struct q_entry_s {
int qe_signo;
sig_t qe_handler;
struct q_entry_s *qe_next;
} q_entry_t;
static struct {
q_entry_t *qe_first;
q_entry_t **qe_last;
} sigqueue = { NULL, &sigqueue.qe_first };
#define SIGQUEUE_INIT(p) do {\
(p)->qe_first = NULL;\
(p)->qe_last = &((p)->qe_first);\
} while (/*CONSTCOND*/ 0)
/*
* The routines alloc_entry() and free_entry() manage the queue
* elements.
*
* Currently, they just assign one element per signo from a fix array
* as we don't support POSIX signal queues. We leave them as this may
* change in the future and the modifications will be isolated.
*/
static q_entry_t *
alloc_entry(int signo)
{
static q_entry_t entries[NSIG];
q_entry_t *e;
/*
* We currently only post one signal per signal number, so
* there is no need to make this complicated.
*/
e = &entries[signo];
if (e->qe_signo != 0)
return NULL;
e->qe_signo = signo;
e->qe_handler = sigarray[signo];
e->qe_next = NULL;
return e;
}
static void
free_entry(q_entry_t *e)
{
e->qe_signo = 0;
e->qe_handler = NULL;
e->qe_next = NULL;
}
/*
* Attempt to post a signal to the sigqueue.
*/
static void
sig_post(int signo)
{
q_entry_t *e;
if (sigarray[signo] == SIG_DFL || sigarray[signo] == SIG_IGN)
return;
e = alloc_entry(signo);
if (e != NULL) {
*sigqueue.qe_last = e;
sigqueue.qe_last = &e->qe_next;
}
}
/*
* Check the sigqueue for any pending signals. If any are found,
* preform the required actions and remove them from the queue.
*/
PUBLIC void
sig_check(void)
{
q_entry_t *e;
sigset_t nset;
sigset_t oset;
void (*handler)(int);
int signo;
(void)sigfillset(&nset);
(void)sigprocmask(SIG_SETMASK, &nset, &oset);
while ((e = sigqueue.qe_first) != NULL) {
signo = e->qe_signo;
handler = e->qe_handler;
/*
* Remove the entry from the queue and free it.
*/
sigqueue.qe_first = e->qe_next;
if (sigqueue.qe_first == NULL)
sigqueue.qe_last = &sigqueue.qe_first;
free_entry(e);
if (handler == SIG_DFL || handler == SIG_IGN) {
assert(/*CONSTCOND*/ 0); /* These should not get posted. */
}
else {
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
handler(signo);
(void)sigprocmask(SIG_SETMASK, &nset, NULL);
}
}
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
}
PUBLIC sig_t
sig_signal(int signo, sig_t handler)
{
sig_t old_handler;
sigset_t nset;
sigset_t oset;
assert(signo > 0 && signo < NSIG);
(void)sigemptyset(&nset);
(void)sigaddset(&nset, signo);
(void)sigprocmask(SIG_BLOCK, &nset, &oset);
old_handler = sigarray[signo];
sigarray[signo] = handler;
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
return old_handler;
}
static void
do_default_handler(int signo, int flags)
{
struct sigaction nsa;
struct sigaction osa;
sigset_t nset;
sigset_t oset;
int save_errno;
save_errno = errno;
(void)sigemptyset(&nsa.sa_mask);
nsa.sa_flags = flags;
nsa.sa_handler = SIG_DFL;
(void)sigaction(signo, &nsa, &osa);
(void)sigemptyset(&nset);
(void)sigaddset(&nset, signo);
(void)sigprocmask(SIG_UNBLOCK, &nset, &oset);
(void)kill(0, signo);
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
(void)sigaction(signo, &osa, NULL);
errno = save_errno;
}
/*
* Our generic signal handler.
*/
static void
sig_handler(int signo)
{
sigset_t nset;
sigset_t oset;
(void)sigfillset(&nset);
(void)sigprocmask(SIG_SETMASK, &nset, &oset);
assert (signo > 0 && signo < NSIG); /* Should be guaranteed. */
sig_post(signo);
switch (signo) {
case SIGCONT:
assert(/*CONSTCOND*/ 0); /* We should not be seeing these. */
do_default_handler(signo, 0);
break;
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
do_default_handler(signo, 0);
break;
case SIGINT:
case SIGHUP:
case SIGQUIT:
case SIGPIPE:
default:
if (sigarray[signo] == SIG_DFL)
do_default_handler(signo, SA_RESTART);
break;
}
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
}
/*
* Setup the signal handlers.
*/
PUBLIC void
sig_setup(void)
{
sigset_t nset;
sigset_t oset;
struct sigaction sa;
struct sigaction osa;
/* Block all signals while setting things. */
(void)sigfillset(&nset);
(void)sigprocmask(SIG_BLOCK, &nset, &oset);
/*
* Flow Control - SIGTSTP, SIGTTIN, SIGTTOU, SIGCONT:
*
* We grab SIGTSTP, SIGTTIN, and SIGTTOU so that we post the
* signals before suspending so that they are available when
* we resume. If we were to use SIGCONT instead, they will
* not get posted until SIGCONT is unblocked, even though the
* process has resumed.
*
* NOTE: We default these to SA_RESTART here, but we need to
* change this in certain cases, e.g., when reading from a
* tty.
*/
(void)sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sig_handler;
(void)sigaction(SIGTSTP, &sa, NULL);
(void)sigaction(SIGTTIN, &sa, NULL);
(void)sigaction(SIGTTOU, &sa, NULL);
/*
* SIGHUP, SIGINT, and SIGQUIT:
*
* SIGHUP and SIGINT are trapped unless they are being
* ignored.
*
* Currently, we let the default handler deal with SIGQUIT.
*/
(void)sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sig_handler;
if (sigaction(SIGHUP, &sa, &osa) != -1 && osa.sa_handler == SIG_IGN)
(void)signal(SIGHUP, SIG_IGN);
if (sigaction(SIGINT, &sa, &osa) != -1 && osa.sa_handler == SIG_IGN)
(void)signal(SIGINT, SIG_IGN);
#if 0
if (signal(SIGQUIT, SIG_DFL) == SIG_IGN)
(void)signal(SIGQUIT, SIG_IGN);
#endif
/*
* SIGCHLD and SIGPIPE:
*
* SIGCHLD is setup early in main. The handler lives in
* popen.c as it uses internals of that module.
*
* SIGPIPE is grabbed here. It is only used in
* lex.c:setup_piping(), cmd1.c:type1(), and cmd1.c:pipecmd().
*/
(void)sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sig_handler;
(void)sigaction(SIGPIPE, &sa, NULL);
/*
* Make sure our structures are initialized.
* XXX: This should be unnecessary.
*/
(void)memset(sigarray, 0, sizeof(sigarray));
SIGQUEUE_INIT(&sigqueue);
/* Restore the signal mask. */
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
}
static struct { /* data shared by sig_hold() and sig_release() */
int depth; /* depth of sig_hold() */
sigset_t oset; /* old signal mask saved by sig_hold() */
} hold;
/*
* Hold signals SIGHUP, SIGINT, and SIGQUIT.
*/
PUBLIC void
sig_hold(void)
{
sigset_t nset;
if (hold.depth++ == 0) {
(void)sigemptyset(&nset);
(void)sigaddset(&nset, SIGHUP);
(void)sigaddset(&nset, SIGINT);
(void)sigaddset(&nset, SIGQUIT);
(void)sigprocmask(SIG_BLOCK, &nset, &hold.oset);
}
}
/*
* Release signals SIGHUP, SIGINT, and SIGQUIT.
*/
PUBLIC void
sig_release(void)
{
if (--hold.depth == 0)
(void)sigprocmask(SIG_SETMASK, &hold.oset, NULL);
}
/*
* Unblock and ignore a signal.
*/
PUBLIC int
sig_ignore(int sig, struct sigaction *osa, sigset_t *oset)
{
struct sigaction act;
sigset_t nset;
int error;
(void)sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
act.sa_handler = SIG_IGN;
error = sigaction(sig, &act, osa);
if (error != -1) {
(void)sigemptyset(&nset);
(void)sigaddset(&nset, sig);
(void)sigprocmask(SIG_UNBLOCK, &nset, oset);
} else if (oset != NULL)
(void)sigprocmask(SIG_UNBLOCK, NULL, oset);
return error;
}
/*
* Restore a signal and the current signal mask.
*/
PUBLIC int
sig_restore(int sig, struct sigaction *osa, sigset_t *oset)
{
int error;
error = 0;
if (oset)
error = sigprocmask(SIG_SETMASK, oset, NULL);
if (osa)
error = sigaction(sig, osa, NULL);
return error;
}
/*
* Change the current flags and (optionally) return the old sigaction
* structure so we can restore things later. This is used to turn
* SA_RESTART on or off.
*/
PUBLIC int
sig_setflags(int signo, int flags, struct sigaction *osa)
{
struct sigaction sa;
if (sigaction(signo, NULL, &sa) == -1)
return -1;
if (osa)
*osa = sa;
sa.sa_flags = flags;
return sigaction(signo, &sa, NULL);
}

44
usr.bin/mail/sig.h Normal file
View File

@ -0,0 +1,44 @@
/* $NetBSD: sig.h,v 1.1 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SIG_H__
#define __SIG_H__
int sig_ignore(int, struct sigaction *, sigset_t *);
int sig_restore(int, struct sigaction *, sigset_t *);
int sig_setflags(int, int, struct sigaction *);
void sig_hold(void);
void sig_release(void); /* XXX: should this be named sig_relse()? */
void sig_check(void);
void sig_setup(void);
sig_t sig_signal(int, sig_t);
#endif /* __SIG_H__ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: strings.c,v 1.16 2007/10/29 23:20:39 christos Exp $ */
/* $NetBSD: strings.c,v 1.17 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)strings.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: strings.c,v 1.16 2007/10/29 23:20:39 christos Exp $");
__RCSID("$NetBSD: strings.c,v 1.17 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -61,7 +61,7 @@ __RCSID("$NetBSD: strings.c,v 1.16 2007/10/29 23:20:39 christos Exp $");
static struct strings {
char *s_topFree; /* Beginning of this area */
char *s_nextFree; /* Next alloctable place here */
unsigned s_nleft; /* Number of bytes left here */
size_t s_nleft; /* Number of bytes left here */
} stringdope[NSPACE];
/*
@ -71,7 +71,6 @@ static struct strings {
* The string spaces are of exponentially increasing size, to satisfy
* the occasional user with enormous string size requests.
*/
PUBLIC void *
salloc(size_t size)
{
@ -94,7 +93,7 @@ salloc(size_t size)
if (sp >= &stringdope[NSPACE])
errx(1, "String too large");
if (sp->s_topFree == NULL) {
idx = sp - &stringdope[0];
idx = (int)(sp - &stringdope[0]);
sp->s_topFree = malloc(STRINGSIZE << idx);
if (sp->s_topFree == NULL)
errx(1, "No room for space %d", idx);

View File

@ -1,4 +1,4 @@
/* $NetBSD: support.c,v 1.21 2008/04/24 01:27:07 christos Exp $ */
/* $NetBSD: support.c,v 1.22 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)aux.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: support.c,v 1.21 2008/04/24 01:27:07 christos Exp $");
__RCSID("$NetBSD: support.c,v 1.22 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -169,7 +169,7 @@ argcount(char **argv)
for (ap = argv; *ap++ != NULL; /*EMPTY*/)
continue;
return ap - argv - 1;
return (int)(ap - argv - 1);
}
/*
@ -211,7 +211,7 @@ gethfield(FILE *f, char linebuf[], int rem, char **colon)
for (;;) {
if (--rem < 0)
return -1;
if ((c = mail_readline(f, linebuf, LINESIZE)) <= 0)
if ((c = readline(f, linebuf, LINESIZE, 0)) <= 0)
return -1;
for (cp = linebuf;
isprint((unsigned char)*cp) && *cp != ' ' && *cp != ':';
@ -234,11 +234,11 @@ gethfield(FILE *f, char linebuf[], int rem, char **colon)
(void)ungetc(c = getc(f), f);
if (!is_WSP(c))
break;
if ((c = mail_readline(f, line2, LINESIZE)) < 0)
if ((c = readline(f, line2, LINESIZE, 0)) < 0)
break;
rem--;
cp2 = skip_WSP(line2);
c -= cp2 - line2;
c -= (int)(cp2 - line2);
if (cp + c >= linebuf + LINESIZE - 2)
break;
*cp++ = ' ';
@ -271,9 +271,9 @@ hfield(const char field[], const struct message *mp)
#endif
ibuf = setinput(mp);
if ((lc = mp->m_lines - 1) < 0)
if ((lc = (int)(mp->m_lines - 1)) < 0)
return NULL;
if (mail_readline(ibuf, linebuf, LINESIZE) < 0)
if (readline(ibuf, linebuf, LINESIZE, 0) < 0)
return NULL;
while (lc > 0) {
if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
@ -571,7 +571,7 @@ name1(struct message *mp, int reptype)
return cp;
ibuf = setinput(mp);
namebuf[0] = '\0';
if (mail_readline(ibuf, linebuf, LINESIZE) < 0)
if (readline(ibuf, linebuf, LINESIZE, 0) < 0)
return savestr(namebuf);
newname:
for (cp = linebuf; *cp && *cp != ' '; cp++)
@ -582,7 +582,7 @@ name1(struct message *mp, int reptype)
/*EMPTY*/)
*cp2++ = *cp++;
*cp2 = '\0';
if (mail_readline(ibuf, linebuf, LINESIZE) < 0)
if (readline(ibuf, linebuf, LINESIZE, 0) < 0)
return savestr(namebuf);
if ((cp = strchr(linebuf, 'F')) == NULL)
return savestr(namebuf);

View File

@ -1,4 +1,4 @@
/* $NetBSD: thread.c,v 1.7 2009/01/18 01:29:57 lukem Exp $ */
/* $NetBSD: thread.c,v 1.8 2009/04/10 13:08:25 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#ifndef __lint__
__RCSID("$NetBSD: thread.c,v 1.7 2009/01/18 01:29:57 lukem Exp $");
__RCSID("$NetBSD: thread.c,v 1.8 2009/04/10 13:08:25 christos Exp $");
#endif /* not __lint__ */
#include <assert.h>
@ -780,7 +780,7 @@ link_array(struct key_sort_s *marray, size_t mcount)
struct message *lastmp;
lastmp = NULL;
for (i = 0; i < mcount; i++) {
marray[i].mp->m_index = i + 1;
marray[i].mp->m_index = (int)i + 1;
marray[i].mp->m_blink = lastmp;
marray[i].mp->m_flink = NULL;
if (lastmp)

View File

@ -1,4 +1,4 @@
/* $NetBSD: tty.c,v 1.27 2006/11/28 18:45:32 christos Exp $ */
/* $NetBSD: tty.c,v 1.28 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)tty.c 8.2 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: tty.c,v 1.27 2006/11/28 18:45:32 christos Exp $");
__RCSID("$NetBSD: tty.c,v 1.28 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -47,77 +47,55 @@ __RCSID("$NetBSD: tty.c,v 1.27 2006/11/28 18:45:32 christos Exp $");
#include "rcv.h"
#include "extern.h"
#ifdef USE_EDITLINE
#include "complete.h"
# include "complete.h"
#endif
#include "sig.h"
#if !defined(USE_EDITLINE) || !defined(TIOCSTI)
static jmp_buf tty_jmpbuf; /* Place to go when interrupted */
#ifndef USE_EDITLINE
static cc_t c_erase; /* Current erase char */
static cc_t c_kill; /* Current kill char */
#endif
#ifndef USE_EDITLINE
static jmp_buf rewrite; /* Place to go when continued */
#endif
static jmp_buf intjmp; /* Place to go when interrupted */
#ifndef TIOCSTI
# ifndef TIOCSTI
static int ttyset; /* We must now do erase/kill */
#endif
# endif
#endif /* USE_EDITLINE */
/*
* Read up a header from standard input.
* The source string has the preliminary contents to
* be read.
*
* Returns: an salloc'ed copy of the line read if successful, or NULL
* if no characters were read or if an error occurred.
*
*/
#ifdef USE_EDITLINE
static char *
readtty(const char pr[], char src[])
readtty(const char *pr, char *src)
{
char *line;
line = my_gets(&elm.string, pr, src);
#if 0
sig_check();
if (line == NULL)
(void)putc('\n', stdout);
return line ? savestr(line) : __UNCONST("");
#else
if (line)
return savestr(line);
else
return __UNCONST("");
#endif
}
#else /* USE_EDITLINE */
/*
* Receipt continuation.
*/
static void
ttystop(int s)
{
sig_t old_action = signal(s, SIG_DFL);
sigset_t nset;
(void)sigemptyset(&nset);
(void)sigaddset(&nset, s);
(void)sigprocmask(SIG_BLOCK, &nset, NULL);
(void)kill(0, s);
(void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
(void)signal(s, old_action);
longjmp(rewrite, 1);
}
#else /* not USE_EDITLINE */
static char *
readtty(const char pr[], char src[])
readtty(const char *pr, char *src)
{
/* XXX - watch for potential setjmp/longjmp clobbering!
* Currently there appear to be none.
*/
char canonb[LINESIZE];
int c;
char *cp, *cp2;
int c;
#ifdef TIOCSTI
char ch;
static char empty[] = "";
#endif
(void)fputs(pr, stdout);
(void)fflush(stdout);
if (src != NULL && strlen(src) > sizeof(canonb) - 2) {
@ -128,11 +106,12 @@ readtty(const char pr[], char src[])
if (src != NULL)
cp = copy(src, canonb);
else
cp = copy("", canonb);
cp = copy(__UNCONST(""), canonb);
c = *cp;
(void)fputs(canonb, stdout);
(void)fflush(stdout);
#else
cp = src == NULL ? empty : src;
cp = src == NULL ? __UNCONST("") : src;
while ((c = *cp++) != '\0') {
if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
(c_kill != _POSIX_VDISABLE && c == c_kill)) {
@ -143,30 +122,25 @@ readtty(const char pr[], char src[])
(void)ioctl(0, TIOCSTI, &ch);
}
cp = canonb;
*cp = 0;
*cp = '\0';
#endif
cp2 = cp;
while (cp2 < canonb + sizeof(canonb))
*cp2++ = 0;
cp2 = cp;
if (setjmp(rewrite))
goto redo;
(void)signal(SIGTSTP, ttystop);
(void)signal(SIGTTOU, ttystop);
(void)signal(SIGTTIN, ttystop);
clearerr(stdin);
while (cp2 < canonb + sizeof(canonb)) {
cp2 = cp;
while (cp2 < canonb + sizeof(canonb) - 1) {
c = getc(stdin);
if (c == EOF || c == '\n')
sig_check();
if (c == EOF) {
if (feof(stdin))
(void)putc('\n', stdout);
break;
}
if (c == '\n')
break;
*cp2++ = c;
}
*cp2 = 0;
(void)signal(SIGTSTP, SIG_DFL);
(void)signal(SIGTTOU, SIG_DFL);
(void)signal(SIGTTIN, SIG_DFL);
*cp2 = '\0';
if (c == EOF && ferror(stdin)) {
redo:
cp = strlen(canonb) > 0 ? canonb : NULL;
clearerr(stdin);
return readtty(pr, cp);
@ -174,9 +148,13 @@ redo:
#ifndef TIOCSTI
if (cp == NULL || *cp == '\0')
return src;
cp2 = cp;
if (!ttyset)
if (ttyset == 0)
return strlen(canonb) > 0 ? savestr(canonb) : NULL;
/*
* Do erase and kill.
*/
cp2 = cp;
while (*cp != '\0') {
c = *cp++;
if (c_erase != _POSIX_VDISABLE && c == c_erase) {
@ -203,173 +181,193 @@ redo:
}
*cp2 = '\0';
#endif
if (equal("", canonb))
return NULL;
if (canonb[0] == '\0')
return __UNCONST("");
return savestr(canonb);
}
#endif /* USE_EDITLINE */
#ifdef USE_EDITLINE
# define save_erase_and_kill(t) 0
#else
static int
save_erase_and_kill(struct termios *t)
{
# ifndef TIOCSTI
ttyset = 0;
#endif
if (tcgetattr(fileno(stdin), t) == -1) {
warn("tcgetattr");
return -1;
}
c_erase = t->c_cc[VERASE];
c_kill = t->c_cc[VKILL];
return 0;
}
#endif
#if defined(USE_EDITLINE) || defined(TIOCSTI)
# define disable_erase_and_kill(t)
#else
static void
disable_erase_and_kill(struct termios *t)
{
if (ttyset == 0) {
ttyset = 1;
t->c_cc[VERASE] = _POSIX_VDISABLE;
t->c_cc[VKILL] = _POSIX_VDISABLE;
(void)tcsetattr(fileno(stdin), TCSADRAIN, t);
}
}
#endif
#if defined(USE_EDITLINE) || defined(TIOCSTI)
# define restore_erase_and_kill(t)
#else
static void
restore_erase_and_kill(struct termios *t)
{
if (ttyset != 0) {
ttyset = 0;
t->c_cc[VERASE] = c_erase;
t->c_cc[VKILL] = c_kill;
(void)tcsetattr(fileno(stdin), TCSADRAIN, t);
}
}
#endif
/*
* Do a shell-like extraction of a line
* and make a list of name from it.
* Return the list or NULL if none found.
*/
static struct name *
shextract(char *line, int ntype)
{
struct name *begin, *np, *t;
char *argv[MAXARGC];
size_t argc, i;
begin = NULL;
if (line) {
np = NULL;
argc = getrawlist(line, argv, (int)__arraycount(argv));
for (i = 0; i < argc; i++) {
t = nalloc(argv[i], ntype);
if (begin == NULL)
begin = t;
else
np->n_flink = t;
t->n_blink = np;
np = t;
}
}
return begin;
}
/*ARGSUSED*/
static void
ttyint(int s __unused)
tty_sigint(int signo __unused)
{
longjmp(intjmp, 1);
longjmp(tty_jmpbuf, 1);
}
/*
* Read all relevant header fields.
* Returns 0 on success; 1 if there was an error or signal.
*/
PUBLIC int
grabh(struct header *hp, int gflags)
{
struct termios ttybuf;
/* The following are declared volatile to avoid longjmp
* clobbering, though they seem safe without it! */
sig_t volatile saveint;
sig_t volatile savetstp;
sig_t volatile savettou;
sig_t volatile savettin;
#ifndef TIOCSTI
sig_t volatile savequit;
#else
# ifdef TIOCEXT
int volatile extproc;
# endif /* TIOCEXT */
#endif /* TIOCSTI */
sig_t volatile old_sigint;
int retval;
#ifndef USE_EDITLINE
struct termios ttybuf;
# if defined(TIOCSTI) && defined(TIOCEXT)
int extproc;
# endif
savetstp = signal(SIGTSTP, SIG_DFL);
savettou = signal(SIGTTOU, SIG_DFL);
savettin = signal(SIGTTIN, SIG_DFL);
#ifndef TIOCSTI
ttyset = 0;
#endif
if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
warn("tcgetattr");
if (save_erase_and_kill(&ttybuf))
return -1;
}
#if !defined(USE_EDITLINE) || !defined(TIOCSTI)
c_erase = ttybuf.c_cc[VERASE];
c_kill = ttybuf.c_cc[VKILL];
#endif
#ifndef TIOCSTI
ttybuf.c_cc[VERASE] = _POSIX_VDISABLE;
ttybuf.c_cc[VKILL] = _POSIX_VDISABLE;
if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
(void)signal(SIGINT, SIG_DFL);
if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
(void)signal(SIGQUIT, SIG_DFL);
#else
# ifdef TIOCEXT
# if defined(TIOCSTI) && defined(TIOCEXT)
extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
if (extproc) {
int flag;
flag = 0;
if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
if (ioctl(fileno(stdin), TIOCEXT, &flag) == -1)
warn("TIOCEXT: off");
}
# endif /* TIOCEXT */
saveint = signal(SIGINT, ttyint); /* must precede setjmp to be saved */
if ((retval = setjmp(intjmp)) != 0) {
(void)fputc('\n', stdout);
# endif
#endif /* USE_EDITLINE */
sig_check();
old_sigint = sig_signal(SIGINT, tty_sigint);
/* return here if we detect a SIGINT */
if ((retval = setjmp(tty_jmpbuf)) != 0) {
(void)putc('\n', stdout);
goto out;
}
#endif
/*
* Do this irrespective of whether the initial string is empty.
* Otherwise, the editing is inconsistent.
*/
disable_erase_and_kill(&ttybuf);
if (gflags & GTO) {
#ifndef TIOCSTI
if (!ttyset && hp->h_to != NULL)
ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
hp->h_to =
extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
}
if (gflags & GSUBJECT) {
#ifndef TIOCSTI
if (!ttyset && hp->h_subject != NULL)
ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
hp->h_subject = readtty("Subject: ", hp->h_subject);
}
if (gflags & GCC) {
#ifndef TIOCSTI
if (!ttyset && hp->h_cc != NULL)
ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
hp->h_cc =
extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
}
if (gflags & GBCC) {
#ifndef TIOCSTI
if (!ttyset && hp->h_bcc != NULL)
ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
hp->h_bcc =
extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
}
if (gflags & GSMOPTS) {
char *smopts;
#ifndef TIOCSTI
if (!ttyset && hp->h_smopts != NULL)
ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
smopts = readtty("Smopts: ", detract(hp->h_smopts, GSMOPTS));
/* Parse smopts with getrawlist() rather than expand()
* to get a shell-like expansion.
*/
hp->h_smopts = NULL;
if (smopts) {
struct name *np, *t;
char *argv[MAXARGC];
int argc, i;
np = NULL;
argc = getrawlist(smopts, argv, sizeof(argv)/sizeof(*argv));
for (i = 0; i < argc; i++) {
t = nalloc(argv[i], GSMOPTS);
if (hp->h_smopts == NULL)
hp->h_smopts = t;
else
np->n_flink = t;
t->n_blink = np;
np = t;
}
}
hp->h_smopts =
shextract(readtty("Smopts: ", detract(hp->h_smopts, 0)),
GSMOPTS);
}
#ifdef MIME_SUPPORT
if (gflags & GSMOPTS) { /* XXX - Use a new flag for this? */
if (hp->h_attach) {
struct attachment *ap;
int i;
i = 0;
for (ap = hp->h_attach; ap; ap = ap->a_flink)
i++;
(void)printf("Attachment%s: %d\n", i > 1 ? "s" : "", i);
}
#endif
}
#ifdef TIOCSTI
out:
#endif
(void)signal(SIGTSTP, savetstp);
(void)signal(SIGTTOU, savettou);
(void)signal(SIGTTIN, savettin);
#ifndef TIOCSTI
ttybuf.c_cc[VERASE] = c_erase;
ttybuf.c_cc[VKILL] = c_kill;
if (ttyset)
tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
(void)signal(SIGQUIT, savequit);
#else
# ifdef TIOCEXT
out:
restore_erase_and_kill(&ttybuf);
#ifndef USE_EDITLINE
# if defined(TIOCSTI) && defined(TIOCEXT)
if (extproc) {
int flag;
flag = 1;
if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
if (ioctl(fileno(stdin), TIOCEXT, &flag) == -1)
warn("TIOCEXT: on");
}
# endif /* TIOCEXT */
# endif
#endif
(void)signal(SIGINT, saveint);
(void)sig_signal(SIGINT, old_sigint);
sig_check();
return retval;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: version.c,v 1.12 2007/02/15 17:18:15 christos Exp $ */
/* $NetBSD: version.c,v 1.13 2009/04/10 13:08:25 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)version.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: version.c,v 1.12 2007/02/15 17:18:15 christos Exp $");
__RCSID("$NetBSD: version.c,v 1.13 2009/04/10 13:08:25 christos Exp $");
#endif
#endif /* not lint */
@ -45,4 +45,4 @@ __RCSID("$NetBSD: version.c,v 1.12 2007/02/15 17:18:15 christos Exp $");
* Just keep track of the date/sid of this version of Mail.
* Load this file first to get a "total" Mail version.
*/
const char *version = "9.0beta 2007-02-15";
const char *version = "9.1alpha 2009-02-25";