Import NetBSD fmt(1)
This requires importing a few files from mail(1) already. Importing the rest of mail(1) is left to future work. Change-Id: If96513a306245cd7fb64660758d0dbd29a36e87c
This commit is contained in:
parent
045e0ed35c
commit
5ae330e220
|
|
@ -328,6 +328,7 @@
|
|||
./usr/bin/flex++ minix-base
|
||||
./usr/bin/flex minix-base
|
||||
./usr/bin/flock minix-base
|
||||
./usr/bin/fmt minix-base
|
||||
./usr/bin/fold minix-base
|
||||
./usr/bin/format minix-base
|
||||
./usr/bin/fpr minix-base
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@
|
|||
./usr/libdata/debug/usr/bin/finger.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/bin/fix.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/bin/flock.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/bin/fmt.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/bin/fold.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/bin/format.debug minix-debug debug
|
||||
./usr/libdata/debug/usr/bin/fpr.debug minix-debug debug
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@
|
|||
./usr/man/man1/flex.1 minix-man
|
||||
./usr/man/man1/flexdoc.1 minix-man obsolete
|
||||
./usr/man/man1/flock.1 minix-man
|
||||
./usr/man/man1/fmt.1 minix-man
|
||||
./usr/man/man1/fold.1 minix-man
|
||||
./usr/man/man1/for.1 minix-man obsolete
|
||||
./usr/man/man1/foreach.1 minix-man
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ SUBDIR= asa \
|
|||
column comm csplit ctags cut \
|
||||
deroff dirname du \
|
||||
env expand \
|
||||
false find finger flock fold fpr from \
|
||||
false find finger flock fold fmt fpr from \
|
||||
fsplit ftp genassym gencat \
|
||||
getopt \
|
||||
head hexdump id indent infocmp ipcrm ipcs join jot \
|
||||
|
|
|
|||
12
usr.bin/fmt/Makefile
Normal file
12
usr.bin/fmt/Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $NetBSD: Makefile,v 1.10 2009/04/14 22:15:20 lukem Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= fmt
|
||||
SRCS= fmt.c head.c
|
||||
CPPFLAGS+= -DFMT_PROG
|
||||
|
||||
.PATH: ${NETBSDSRCDIR}/usr.bin/mail
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
99
usr.bin/fmt/buffer.h
Normal file
99
usr.bin/fmt/buffer.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* $NetBSD: buffer.h,v 1.4 2008/04/28 20:24:12 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Christos Zoulas.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
|
||||
#define BUF_SIZE BUFSIZ
|
||||
struct buffer {
|
||||
char *ptr;
|
||||
char *bptr;
|
||||
char *eptr;
|
||||
};
|
||||
|
||||
static void
|
||||
buf_init(struct buffer *buf)
|
||||
{
|
||||
buf->ptr = buf->bptr = malloc(BUF_SIZE);
|
||||
if (buf->ptr == NULL)
|
||||
err(1, "Cannot allocate buffer");
|
||||
buf->eptr = buf->ptr + BUF_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
buf_end(struct buffer *buf)
|
||||
{
|
||||
free(buf->bptr);
|
||||
}
|
||||
|
||||
static void
|
||||
buf_grow(struct buffer *buf, size_t minsize)
|
||||
{
|
||||
ptrdiff_t diff;
|
||||
size_t len = (buf->eptr - buf->bptr) +
|
||||
(minsize > BUF_SIZE ? minsize : BUF_SIZE);
|
||||
char *nptr = realloc(buf->bptr, len);
|
||||
|
||||
if (nptr == NULL)
|
||||
err(1, "Cannot grow buffer");
|
||||
|
||||
if (nptr == buf->bptr) {
|
||||
buf->eptr = buf->bptr + len;
|
||||
return;
|
||||
}
|
||||
|
||||
diff = nptr - buf->bptr;
|
||||
buf->bptr += diff;
|
||||
buf->eptr = buf->bptr + len;
|
||||
buf->ptr += diff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
buf_putc(struct buffer *buf, char c)
|
||||
{
|
||||
if (buf->ptr >= buf->eptr)
|
||||
buf_grow(buf, 1);
|
||||
*buf->ptr++ = c;
|
||||
}
|
||||
|
||||
static inline void
|
||||
buf_reset(struct buffer *buf)
|
||||
{
|
||||
buf->ptr = buf->bptr;
|
||||
}
|
||||
|
||||
static inline char
|
||||
buf_unputc(struct buffer *buf)
|
||||
{
|
||||
return buf->ptr > buf->bptr ? *--buf->ptr : '\0';
|
||||
}
|
||||
113
usr.bin/fmt/fmt.1
Normal file
113
usr.bin/fmt/fmt.1
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
.\" $NetBSD: fmt.1,v 1.13 2012/06/30 21:31:15 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 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.
|
||||
.\"
|
||||
.\" @(#)fmt.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 31, 2012
|
||||
.Dt FMT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fmt
|
||||
.Nd simple text formatter
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl Cr
|
||||
.Oo
|
||||
.Ar goal
|
||||
.Op Ar maximum
|
||||
.Oc
|
||||
.Op name ...
|
||||
.Nm
|
||||
.Op Fl Cr
|
||||
.Op Fl g Ar goal
|
||||
.Op Fl m Ar maximum
|
||||
.Op Fl w Ar maximum
|
||||
.Op name ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a simple text formatter which reads the concatenation of input
|
||||
files (or standard input if none are given) and produces on standard
|
||||
output a version of its input with lines as close to the
|
||||
.Ar goal
|
||||
length as possible without exceeding the
|
||||
.Ar maximum .
|
||||
The
|
||||
.Ar goal
|
||||
length defaults to 65 and the
|
||||
.Ar maximum
|
||||
to 75.
|
||||
The spacing at the beginning of the input lines is preserved in
|
||||
the output, as are blank lines and interword spacing.
|
||||
In non raw mode, lines that look like mail headers or begin with
|
||||
a period are not formatted.
|
||||
.Pp
|
||||
.Bl -tag -width ".Fl m Ar maximum"
|
||||
.It Fl C
|
||||
instructs
|
||||
.Nm
|
||||
to center the text.
|
||||
.It Fl g Ar goal
|
||||
New way to set the goal length.
|
||||
.It Fl m Ar maximum
|
||||
New way to set the maximum length.
|
||||
.It Fl w Ar maximum
|
||||
New way to set the maximum length.
|
||||
.It Fl r
|
||||
Raw mode; formats all lines and does not make exceptions for lines
|
||||
that start with a period or look like mail headers.
|
||||
.El
|
||||
.Pp
|
||||
.Nm
|
||||
is meant to format mail messages prior to sending, but may also be useful
|
||||
for other simple tasks.
|
||||
For instance, within visual mode of the
|
||||
.Xr ex 1
|
||||
editor (e.g.,
|
||||
.Xr vi 1 )
|
||||
the command
|
||||
.Pp
|
||||
.Dl \&!}fmt
|
||||
.Pp
|
||||
will reformat a paragraph, evening the lines.
|
||||
.Sh SEE ALSO
|
||||
.Xr mail 1 ,
|
||||
.Xr nroff 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 3 .
|
||||
.\" .Sh AUTHORS
|
||||
.\" Kurt Shoens
|
||||
.\" .Pp
|
||||
.\" Liz Allen (added goal length concept)
|
||||
.Sh BUGS
|
||||
The program was designed to be simple and fast \- for more complex
|
||||
operations, the standard text processors are likely to be more
|
||||
appropriate.
|
||||
555
usr.bin/fmt/fmt.c
Normal file
555
usr.bin/fmt/fmt.c
Normal file
|
|
@ -0,0 +1,555 @@
|
|||
/* $NetBSD: fmt.c,v 1.32 2012/06/30 21:31:15 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
|
||||
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)fmt.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif
|
||||
__RCSID("$NetBSD: fmt.c,v 1.32 2012/06/30 21:31:15 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "buffer.h"
|
||||
|
||||
/*
|
||||
* fmt -- format the concatenation of input files or standard input
|
||||
* onto standard output. Designed for use with Mail ~|
|
||||
*
|
||||
* Syntax : fmt [ goal [ max ] ] [ name ... ]
|
||||
* Authors: Kurt Shoens (UCB) 12/7/78;
|
||||
* Liz Allen (UMCP) 2/24/83 [Addition of goal length concept].
|
||||
*/
|
||||
|
||||
/* LIZ@UOM 6/18/85 --New variables goal_length and max_length */
|
||||
#define GOAL_LENGTH 65
|
||||
#define MAX_LENGTH 75
|
||||
static size_t goal_length; /* Target or goal line length in output */
|
||||
static size_t max_length; /* Max line length in output */
|
||||
static size_t pfx; /* Current leading blank count */
|
||||
static int raw; /* Don't treat mail specially */
|
||||
static int lineno; /* Current input line */
|
||||
static int mark; /* Last place we saw a head line */
|
||||
static int center;
|
||||
static struct buffer outbuf;
|
||||
|
||||
static const char *headnames[] = {"To", "Subject", "Cc", 0};
|
||||
|
||||
static void usage(void) __dead;
|
||||
static int getnum(const char *, const char *, size_t *, int);
|
||||
static void fmt(FILE *);
|
||||
static int ispref(const char *, const char *);
|
||||
static void leadin(void);
|
||||
static void oflush(void);
|
||||
static void pack(const char *, size_t);
|
||||
static void prefix(const struct buffer *, int);
|
||||
static void split(const char *, int);
|
||||
static void tabulate(struct buffer *);
|
||||
|
||||
|
||||
int ishead(const char *);
|
||||
|
||||
/*
|
||||
* Drive the whole formatter by managing input files. Also,
|
||||
* cause initialization of the output stuff and flush it out
|
||||
* at the end.
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
FILE *fi;
|
||||
int errs = 0;
|
||||
int compat = 1;
|
||||
int c;
|
||||
|
||||
goal_length = GOAL_LENGTH;
|
||||
max_length = MAX_LENGTH;
|
||||
buf_init(&outbuf);
|
||||
lineno = 1;
|
||||
mark = -10;
|
||||
|
||||
setprogname(*argv);
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
while ((c = getopt(argc, argv, "Cg:m:rw:")) != -1)
|
||||
switch (c) {
|
||||
case 'C':
|
||||
center++;
|
||||
break;
|
||||
case 'g':
|
||||
(void)getnum(optarg, "goal", &goal_length, 1);
|
||||
compat = 0;
|
||||
break;
|
||||
case 'm':
|
||||
case 'w':
|
||||
(void)getnum(optarg, "max", &max_length, 1);
|
||||
compat = 0;
|
||||
break;
|
||||
case 'r':
|
||||
raw++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* compatibility with old usage.
|
||||
*/
|
||||
if (compat && argc > 0 && getnum(*argv, "goal", &goal_length, 0)) {
|
||||
argv++;
|
||||
argc--;
|
||||
if (argc > 0 && getnum(*argv, "max", &max_length, 0)) {
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_length <= goal_length) {
|
||||
errx(1, "Max length (%zu) must be greater than goal "
|
||||
"length (%zu)", max_length, goal_length);
|
||||
}
|
||||
if (argc == 0) {
|
||||
fmt(stdin);
|
||||
oflush();
|
||||
return 0;
|
||||
}
|
||||
for (;argc; argc--, argv++) {
|
||||
if ((fi = fopen(*argv, "r")) == NULL) {
|
||||
warn("Cannot open `%s'", *argv);
|
||||
errs++;
|
||||
continue;
|
||||
}
|
||||
fmt(fi);
|
||||
(void)fclose(fi);
|
||||
}
|
||||
oflush();
|
||||
buf_end(&outbuf);
|
||||
return errs;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-Cr] [-g <goal>] [-m|w <max>] [<files>..]\n"
|
||||
"\t %s [-Cr] [<goal>] [<max>] [<files>]\n",
|
||||
getprogname(), getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
getnum(const char *str, const char *what, size_t *res, int badnum)
|
||||
{
|
||||
unsigned long ul;
|
||||
char *ep;
|
||||
|
||||
errno = 0;
|
||||
ul = strtoul(str, &ep, 0);
|
||||
if (*str != '\0' && *ep == '\0') {
|
||||
if ((errno == ERANGE && ul == ULONG_MAX) || ul > SIZE_T_MAX)
|
||||
errx(1, "%s number `%s' too big", what, str);
|
||||
*res = (size_t)ul;
|
||||
return 1;
|
||||
} else if (badnum)
|
||||
errx(1, "Bad %s number `%s'", what, str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read up characters from the passed input file, forming lines,
|
||||
* doing ^H processing, expanding tabs, stripping trailing blanks,
|
||||
* and sending each line down for analysis.
|
||||
*/
|
||||
static void
|
||||
fmt(FILE *fi)
|
||||
{
|
||||
struct buffer lbuf, cbuf;
|
||||
char *cp, *cp2;
|
||||
int c, add_space;
|
||||
size_t len, col, i;
|
||||
|
||||
if (center) {
|
||||
for (;;) {
|
||||
cp = fgetln(fi, &len);
|
||||
if (!cp)
|
||||
return;
|
||||
|
||||
/* skip over leading space */
|
||||
while (len > 0) {
|
||||
if (!isspace((unsigned char)*cp))
|
||||
break;
|
||||
cp++;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* clear trailing space */
|
||||
while (len > 0) {
|
||||
if (!isspace((unsigned char)cp[len-1]))
|
||||
break;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
/* blank line */
|
||||
(void)putchar('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (goal_length > len) {
|
||||
for (i = 0; i < (goal_length - len) / 2; i++) {
|
||||
(void)putchar(' ');
|
||||
}
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
(void)putchar(cp[i]);
|
||||
}
|
||||
(void)putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
buf_init(&lbuf);
|
||||
buf_init(&cbuf);
|
||||
c = getc(fi);
|
||||
|
||||
while (c != EOF) {
|
||||
/*
|
||||
* Collect a line, doing ^H processing.
|
||||
* Leave tabs for now.
|
||||
*/
|
||||
buf_reset(&lbuf);
|
||||
while (c != '\n' && c != EOF) {
|
||||
if (c == '\b') {
|
||||
(void)buf_unputc(&lbuf);
|
||||
c = getc(fi);
|
||||
continue;
|
||||
}
|
||||
if(!(isprint(c) || c == '\t' || c >= 160)) {
|
||||
c = getc(fi);
|
||||
continue;
|
||||
}
|
||||
buf_putc(&lbuf, c);
|
||||
c = getc(fi);
|
||||
}
|
||||
buf_putc(&lbuf, '\0');
|
||||
(void)buf_unputc(&lbuf);
|
||||
add_space = c != EOF;
|
||||
|
||||
/*
|
||||
* Expand tabs on the way.
|
||||
*/
|
||||
col = 0;
|
||||
cp = lbuf.bptr;
|
||||
buf_reset(&cbuf);
|
||||
while ((c = *cp++) != '\0') {
|
||||
if (c != '\t') {
|
||||
col++;
|
||||
buf_putc(&cbuf, c);
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
buf_putc(&cbuf, ' ');
|
||||
col++;
|
||||
} while ((col & 07) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Swipe trailing blanks from the line.
|
||||
*/
|
||||
for (cp2 = cbuf.ptr - 1; cp2 >= cbuf.bptr && *cp2 == ' '; cp2--)
|
||||
continue;
|
||||
cbuf.ptr = cp2 + 1;
|
||||
buf_putc(&cbuf, '\0');
|
||||
(void)buf_unputc(&cbuf);
|
||||
prefix(&cbuf, add_space);
|
||||
if (c != EOF)
|
||||
c = getc(fi);
|
||||
}
|
||||
buf_end(&cbuf);
|
||||
buf_end(&lbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a line devoid of tabs and other garbage and determine its
|
||||
* blank prefix. If the indent changes, call for a linebreak.
|
||||
* If the input line is blank, echo the blank line on the output.
|
||||
* Finally, if the line minus the prefix is a mail header, try to keep
|
||||
* it on a line by itself.
|
||||
*/
|
||||
static void
|
||||
prefix(const struct buffer *buf, int add_space)
|
||||
{
|
||||
const char *cp;
|
||||
const char **hp;
|
||||
size_t np;
|
||||
int h;
|
||||
|
||||
if (buf->ptr == buf->bptr) {
|
||||
oflush();
|
||||
(void)putchar('\n');
|
||||
return;
|
||||
}
|
||||
for (cp = buf->bptr; *cp == ' '; cp++)
|
||||
continue;
|
||||
np = cp - buf->bptr;
|
||||
|
||||
/*
|
||||
* The following horrible expression attempts to avoid linebreaks
|
||||
* when the indent changes due to a paragraph.
|
||||
*/
|
||||
if (np != pfx && (np > pfx || abs((int)(pfx - np)) > 8))
|
||||
oflush();
|
||||
if (!raw) {
|
||||
if ((h = ishead(cp)) != 0) {
|
||||
oflush();
|
||||
mark = lineno;
|
||||
}
|
||||
if (lineno - mark < 3 && lineno - mark > 0)
|
||||
for (hp = &headnames[0]; *hp != NULL; hp++)
|
||||
if (ispref(*hp, cp)) {
|
||||
h = 1;
|
||||
oflush();
|
||||
break;
|
||||
}
|
||||
if (!h && (h = (*cp == '.')))
|
||||
oflush();
|
||||
} else
|
||||
h = 0;
|
||||
pfx = np;
|
||||
if (h) {
|
||||
pack(cp, (size_t)(buf->ptr - cp));
|
||||
oflush();
|
||||
} else
|
||||
split(cp, add_space);
|
||||
lineno++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split up the passed line into output "words" which are
|
||||
* maximal strings of non-blanks with the blank separation
|
||||
* attached at the end. Pass these words along to the output
|
||||
* line packer.
|
||||
*/
|
||||
static void
|
||||
split(const char line[], int add_space)
|
||||
{
|
||||
const char *cp;
|
||||
struct buffer word;
|
||||
size_t wlen;
|
||||
|
||||
buf_init(&word);
|
||||
cp = line;
|
||||
while (*cp) {
|
||||
buf_reset(&word);
|
||||
wlen = 0;
|
||||
|
||||
/*
|
||||
* Collect a 'word,' allowing it to contain escaped white
|
||||
* space.
|
||||
*/
|
||||
while (*cp && *cp != ' ') {
|
||||
if (*cp == '\\' && isspace((unsigned char)cp[1]))
|
||||
buf_putc(&word, *cp++);
|
||||
buf_putc(&word, *cp++);
|
||||
wlen++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Guarantee a space at end of line. Two spaces after end of
|
||||
* sentence punctuation.
|
||||
*/
|
||||
if (*cp == '\0' && add_space) {
|
||||
buf_putc(&word, ' ');
|
||||
if (strchr(".:!", cp[-1]))
|
||||
buf_putc(&word, ' ');
|
||||
}
|
||||
while (*cp == ' ')
|
||||
buf_putc(&word, *cp++);
|
||||
|
||||
buf_putc(&word, '\0');
|
||||
(void)buf_unputc(&word);
|
||||
|
||||
pack(word.bptr, wlen);
|
||||
}
|
||||
buf_end(&word);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output section.
|
||||
* Build up line images from the words passed in. Prefix
|
||||
* each line with correct number of blanks.
|
||||
*
|
||||
* At the bottom of this whole mess, leading tabs are reinserted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pack a word onto the output line. If this is the beginning of
|
||||
* the line, push on the appropriately-sized string of blanks first.
|
||||
* If the word won't fit on the current line, flush and begin a new
|
||||
* line. If the word is too long to fit all by itself on a line,
|
||||
* just give it its own and hope for the best.
|
||||
*
|
||||
* LIZ@UOM 6/18/85 -- If the new word will fit in at less than the
|
||||
* goal length, take it. If not, then check to see if the line
|
||||
* will be over the max length; if so put the word on the next
|
||||
* line. If not, check to see if the line will be closer to the
|
||||
* goal length with or without the word and take it or put it on
|
||||
* the next line accordingly.
|
||||
*/
|
||||
|
||||
static void
|
||||
pack(const char *word, size_t wlen)
|
||||
{
|
||||
const char *cp;
|
||||
size_t s, t;
|
||||
|
||||
if (outbuf.bptr == outbuf.ptr)
|
||||
leadin();
|
||||
/*
|
||||
* LIZ@UOM 6/18/85 -- change condition to check goal_length; s is the
|
||||
* length of the line before the word is added; t is now the length
|
||||
* of the line after the word is added
|
||||
*/
|
||||
s = outbuf.ptr - outbuf.bptr;
|
||||
t = wlen + s;
|
||||
if ((t <= goal_length) || ((t <= max_length) &&
|
||||
(s <= goal_length) && (t - goal_length <= goal_length - s))) {
|
||||
/*
|
||||
* In like flint!
|
||||
*/
|
||||
for (cp = word; *cp;)
|
||||
buf_putc(&outbuf, *cp++);
|
||||
return;
|
||||
}
|
||||
if (s > pfx) {
|
||||
oflush();
|
||||
leadin();
|
||||
}
|
||||
for (cp = word; *cp;)
|
||||
buf_putc(&outbuf, *cp++);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is anything on the current output line, send it on
|
||||
* its way. Reset outbuf.
|
||||
*/
|
||||
static void
|
||||
oflush(void)
|
||||
{
|
||||
if (outbuf.bptr == outbuf.ptr)
|
||||
return;
|
||||
buf_putc(&outbuf, '\0');
|
||||
(void)buf_unputc(&outbuf);
|
||||
tabulate(&outbuf);
|
||||
buf_reset(&outbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the passed line buffer, insert leading tabs where possible, and
|
||||
* output on standard output (finally).
|
||||
*/
|
||||
static void
|
||||
tabulate(struct buffer *buf)
|
||||
{
|
||||
char *cp;
|
||||
size_t b, t;
|
||||
|
||||
/*
|
||||
* Toss trailing blanks in the output line.
|
||||
*/
|
||||
for (cp = buf->ptr - 1; cp >= buf->bptr && *cp == ' '; cp--)
|
||||
continue;
|
||||
*++cp = '\0';
|
||||
|
||||
/*
|
||||
* Count the leading blank space and tabulate.
|
||||
*/
|
||||
for (cp = buf->bptr; *cp == ' '; cp++)
|
||||
continue;
|
||||
b = cp - buf->bptr;
|
||||
t = b / 8;
|
||||
b = b % 8;
|
||||
if (t > 0)
|
||||
do
|
||||
(void)putchar('\t');
|
||||
while (--t);
|
||||
if (b > 0)
|
||||
do
|
||||
(void)putchar(' ');
|
||||
while (--b);
|
||||
while (*cp)
|
||||
(void)putchar(*cp++);
|
||||
(void)putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the output line with the appropriate number of
|
||||
* leading blanks.
|
||||
*/
|
||||
static void
|
||||
leadin(void)
|
||||
{
|
||||
size_t b;
|
||||
|
||||
buf_reset(&outbuf);
|
||||
|
||||
for (b = 0; b < pfx; b++)
|
||||
buf_putc(&outbuf, ' ');
|
||||
}
|
||||
|
||||
/*
|
||||
* Is s1 a prefix of s2??
|
||||
*/
|
||||
static int
|
||||
ispref(const char *s1, const char *s2)
|
||||
{
|
||||
|
||||
while (*s1++ == *s2)
|
||||
continue;
|
||||
return *s1 == '\0';
|
||||
}
|
||||
468
usr.bin/mail/def.h
Normal file
468
usr.bin/mail/def.h
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
/* $NetBSD: def.h,v 1.28 2014/10/18 08:33:30 snj 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.
|
||||
*
|
||||
* @(#)def.h 8.4 (Berkeley) 4/20/95
|
||||
* $NetBSD: def.h,v 1.28 2014/10/18 08:33:30 snj Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Mail -- a mail program
|
||||
*
|
||||
* Author: Kurt Shoens (UCB) March 25, 1978
|
||||
*/
|
||||
|
||||
#ifndef __DEF_H__
|
||||
#define __DEF_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <vis.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
#define APPEND /* New mail goes to end of mailbox */
|
||||
|
||||
#define COMMENT_CHAR '#' /* Comment character when sourcing */
|
||||
#define ESCAPE '~' /* Default escape for sending */
|
||||
#define NMLSIZE 1024 /* max names in a message list */
|
||||
#define PATHSIZE MAXPATHLEN /* Size of pathnames throughout */
|
||||
#define HSHSIZE 59 /* Hash size for aliases and vars */
|
||||
#define LINESIZE BUFSIZ /* max readable line width */
|
||||
#define MAXARGC 1024 /* Maximum list of raw strings */
|
||||
#define MAXEXP 25 /* Maximum expansion of aliases */
|
||||
|
||||
#define PUBLIC /* make it easy to find the entry points */
|
||||
|
||||
/*
|
||||
* User environment variable names.
|
||||
* See complete.h, mime.h, and thread.h for names specific to those modules.
|
||||
*/
|
||||
#define ENAME_INDENT_POSTSCRIPT "indentpostscript"
|
||||
#define ENAME_INDENT_PREAMBLE "indentpreamble"
|
||||
#define ENAME_APPEND "append"
|
||||
#define ENAME_ASK "ask"
|
||||
#define ENAME_ASKBCC "askbcc"
|
||||
#define ENAME_ASKCC "askcc"
|
||||
#define ENAME_ASKSUB "asksub"
|
||||
#define ENAME_AUTOINC "autoinc"
|
||||
#define ENAME_AUTOPRINT "autoprint"
|
||||
#define ENAME_CRT "crt"
|
||||
#define ENAME_DEAD "DEAD"
|
||||
#define ENAME_DEBUG "debug"
|
||||
#define ENAME_DONTSENDEMPTY "dontsendempty"
|
||||
#define ENAME_DOT "dot"
|
||||
#define ENAME_EDITOR "EDITOR"
|
||||
#define ENAME_ENABLE_PIPES "enable-pipes"
|
||||
#define ENAME_ESCAPE "escape"
|
||||
#define ENAME_FOLDER "folder"
|
||||
#define ENAME_HEADER_FORMAT "header-format"
|
||||
#define ENAME_HOLD "hold"
|
||||
#define ENAME_IGNORE "ignore"
|
||||
#define ENAME_IGNOREEOF "ignoreeof"
|
||||
#define ENAME_INDENTPREFIX "indentprefix"
|
||||
#define ENAME_INTERACTIVE "interactive"
|
||||
#define ENAME_KEEP "keep"
|
||||
#define ENAME_KEEPSAVE "keepsave"
|
||||
#define ENAME_LISTER "LISTER"
|
||||
#define ENAME_MBOX "MBOX"
|
||||
#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"
|
||||
#define ENAME_QUIET "quiet"
|
||||
#define ENAME_RECORD "record"
|
||||
#define ENAME_REGEX_SEARCH "regex-search"
|
||||
#define ENAME_REPLYALL "Replyall"
|
||||
#define ENAME_REPLYASRECIPIENT "ReplyAsRecipient"
|
||||
#define ENAME_SCREEN "screen"
|
||||
#define ENAME_SCREENHEIGHT "screenheight"
|
||||
#define ENAME_SCREENWIDTH "screenwidth"
|
||||
#define ENAME_SEARCHHEADERS "searchheaders"
|
||||
#define ENAME_SENDMAIL "sendmail"
|
||||
#define ENAME_SHELL "SHELL"
|
||||
#define ENAME_SHOW_RCPT "show-rcpt"
|
||||
#define ENAME_SMOPTS_VERIFY "smopts-verify"
|
||||
#define ENAME_TOPLINES "toplines"
|
||||
#define ENAME_VERBOSE "verbose"
|
||||
#define ENAME_VISUAL "VISUAL"
|
||||
|
||||
#define equal(a, b) (strcmp(a,b)==0)/* A nice function to string compare */
|
||||
|
||||
struct message {
|
||||
short m_flag; /* flags, see below */
|
||||
short m_offset; /* offset in block of message */
|
||||
long m_block; /* block number of this message */
|
||||
long m_lines; /* Lines in the message */
|
||||
off_t m_size; /* Bytes in the message */
|
||||
long m_blines; /* Body (non-header) lines */
|
||||
|
||||
/*
|
||||
* threading fields
|
||||
*/
|
||||
int m_index; /* message index in this thread */
|
||||
int m_depth; /* depth in thread */
|
||||
struct message *m_flink; /* link to next message */
|
||||
struct message *m_blink; /* link to previous message */
|
||||
struct message *m_clink; /* link to child of this message */
|
||||
struct message *m_plink; /* link to parent of thread */
|
||||
};
|
||||
typedef struct mime_info mime_info_t; /* phantom structure only to attach.c */
|
||||
|
||||
/*
|
||||
* flag bits.
|
||||
*/
|
||||
|
||||
#define MUSED (1<<0) /* entry is used, but this bit isn't */
|
||||
#define MDELETED (1<<1) /* entry has been deleted */
|
||||
#define MSAVED (1<<2) /* entry has been saved */
|
||||
#define MTOUCH (1<<3) /* entry has been noticed */
|
||||
#define MPRESERVE (1<<4) /* keep entry in sys mailbox */
|
||||
#define MMARK (1<<5) /* message is marked! */
|
||||
#define MMODIFY (1<<6) /* message has been modified */
|
||||
#define MNEW (1<<7) /* message has never been seen */
|
||||
#define MREAD (1<<8) /* message has been read sometime. */
|
||||
#define MSTATUS (1<<9) /* message status has changed */
|
||||
#define MBOX (1<<10) /* Send this to mbox, regardless */
|
||||
#define MTAGGED (1<<11) /* message has been tagged */
|
||||
|
||||
/*
|
||||
* Given a file address, determine the block number it represents.
|
||||
*/
|
||||
#define blockof(off) ((int) ((off) / 4096))
|
||||
#define blkoffsetof(off) ((int) ((off) % 4096))
|
||||
#define positionof(block, offset) ((off_t)(block) * 4096 + (offset))
|
||||
|
||||
/*
|
||||
* Format of the command description table.
|
||||
* The actual table is declared and initialized
|
||||
* in lex.c
|
||||
*/
|
||||
struct cmd {
|
||||
const char *c_name; /* Name of command */
|
||||
int (*c_func)(void *); /* Implementor of the command */
|
||||
int c_pipe; /* Pipe output through the pager */
|
||||
# define C_PIPE_PAGER 1 /* enable use of pager */
|
||||
# define C_PIPE_CRT 2 /* use the pager if CRT is defined */
|
||||
# define C_PIPE_SHELL 4 /* enable shell pipes */
|
||||
#ifdef USE_EDITLINE
|
||||
const char *c_complete; /* String describing completion */
|
||||
#endif
|
||||
short c_argtype; /* Type of arglist (see below) */
|
||||
short c_msgflag; /* Required flags of messages */
|
||||
short c_msgmask; /* Relevant flags of messages */
|
||||
};
|
||||
|
||||
/* Yechh, can't initialize unions */
|
||||
|
||||
#define c_minargs c_msgflag /* Minimum argcount for RAWLIST */
|
||||
#define c_maxargs c_msgmask /* Max argcount for RAWLIST */
|
||||
|
||||
/*
|
||||
* Argument types.
|
||||
*/
|
||||
|
||||
#define MSGLIST 0 /* Message list type */
|
||||
#define STRLIST 1 /* A pure string */
|
||||
#define RAWLIST 2 /* Shell string list */
|
||||
#define NOLIST 3 /* Just plain 0 */
|
||||
#define NDMLIST 4 /* Message list, no defaults */
|
||||
|
||||
#define P 0x010 /* Autoprint dot after command */
|
||||
#define I 0x020 /* Interactive command bit */
|
||||
#define M 0x040 /* Legal from send mode bit */
|
||||
#define W 0x080 /* Illegal when read only bit */
|
||||
#define F 0x100 /* Is a conditional command */
|
||||
#define T 0x200 /* Is a transparent command */
|
||||
#define R 0x400 /* Cannot be called from collect */
|
||||
#define ARGTYPE_MASK ~(P|I|M|W|F|T|R)
|
||||
|
||||
/*
|
||||
* Oft-used mask values
|
||||
*/
|
||||
|
||||
#define MMNORM (MDELETED|MSAVED)/* Look at both save and delete bits */
|
||||
#define MMNDEL MDELETED /* Look only at deleted bit */
|
||||
|
||||
/*
|
||||
* Structure used to return a break down of a head
|
||||
* line (hats off to Bill Joy!)
|
||||
*/
|
||||
|
||||
struct headline {
|
||||
char *l_from; /* The name of the sender */
|
||||
char *l_tty; /* His tty string (if any) */
|
||||
char *l_date; /* The entire date string */
|
||||
};
|
||||
|
||||
#define GTO 0x001 /* Grab To: line */
|
||||
#define GSUBJECT 0x002 /* Likewise, Subject: line */
|
||||
#define GCC 0x004 /* And the Cc: line */
|
||||
#define GBCC 0x008 /* And also the Bcc: line */
|
||||
#define GSMOPTS 0x010 /* Grab the sendmail options */
|
||||
#define GMISC 0x020 /* miscellaneous extra fields for sending */
|
||||
#ifdef MIME_SUPPORT
|
||||
#define GMIME 0x040 /* mime flag */
|
||||
#endif
|
||||
#define GMASK (GTO | GSUBJECT | GCC | GBCC | GSMOPTS)
|
||||
/* Mask of places from whence */
|
||||
|
||||
#define GNL 0x100 /* Print blank line after */
|
||||
#define GDEL 0x200 /* Entity removed from list */
|
||||
#define GCOMMA 0x400 /* detract puts in commas */
|
||||
|
||||
#ifdef MIME_SUPPORT
|
||||
/*
|
||||
* Structure of MIME content.
|
||||
*/
|
||||
struct Content {
|
||||
const char *C_type; /* content type */
|
||||
const char *C_encoding; /* content transfer encoding */
|
||||
const char *C_disposition; /* content disposition */
|
||||
const char *C_description; /* content description */
|
||||
const char *C_id; /* content id */
|
||||
};
|
||||
/* Header strings corresponding to the above Content fields. */
|
||||
#define MIME_HDR_TYPE "Content-Type"
|
||||
#define MIME_HDR_ENCODING "Content-Transfer-Encoding"
|
||||
#define MIME_HDR_DISPOSITION "Content-Disposition"
|
||||
#define MIME_HDR_ID "Content-ID"
|
||||
#define MIME_HDR_DESCRIPTION "Content-Description"
|
||||
#define MIME_HDR_VERSION "MIME-Version"
|
||||
/* the value of the MIME-Version field */
|
||||
#define MIME_VERSION "1.0"
|
||||
|
||||
typedef enum {
|
||||
ATTACH_INVALID = 0, /* do not use! */
|
||||
ATTACH_FNAME = 1,
|
||||
ATTACH_MSG = 2,
|
||||
ATTACH_FILENO = 3
|
||||
} attach_t;
|
||||
|
||||
/*
|
||||
* Structure of a MIME attachment.
|
||||
*/
|
||||
struct attachment {
|
||||
struct attachment *a_flink; /* Forward link in list. */
|
||||
struct attachment *a_blink; /* Backward list link */
|
||||
|
||||
attach_t a_type; /* attachment type */
|
||||
#if 1
|
||||
union {
|
||||
char *u_name; /* file name */
|
||||
struct message *u_msg; /* message */
|
||||
int u_fileno; /* file number */
|
||||
} a_u;
|
||||
|
||||
#define a_name a_u.u_name
|
||||
#define a_msg a_u.u_msg
|
||||
#define a_fileno a_u.u_fileno
|
||||
#else
|
||||
char *a_name; /* file name */
|
||||
struct message *a_msg; /* message */
|
||||
int a_fileno; /* file number */
|
||||
#endif
|
||||
|
||||
struct Content a_Content; /* MIME content strings */
|
||||
};
|
||||
#endif /* MIME_SUPPORT */
|
||||
|
||||
/*
|
||||
* Structure used to pass about the current
|
||||
* state of the user-typed message header.
|
||||
*/
|
||||
|
||||
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; /* 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 */
|
||||
struct attachment *h_attach; /* MIME attachments */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of namelist nodes used in processing
|
||||
* the recipients of mail and aliases and all that
|
||||
* kind of stuff.
|
||||
*/
|
||||
|
||||
struct name {
|
||||
struct name *n_flink; /* Forward link in list. */
|
||||
struct name *n_blink; /* Backward list link */
|
||||
short n_type; /* From which list it came */
|
||||
char *n_name; /* This fella's name */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a variable node. All variables are
|
||||
* kept on a singly-linked list of these, rooted by
|
||||
* "variables"
|
||||
*/
|
||||
|
||||
struct var {
|
||||
struct var *v_link; /* Forward link to next variable */
|
||||
char *v_name; /* The variable's name */
|
||||
char *v_value; /* And its current value */
|
||||
};
|
||||
|
||||
struct group {
|
||||
struct group *ge_link; /* Next person in this group */
|
||||
char *ge_name; /* This person's user name */
|
||||
};
|
||||
|
||||
struct grouphead {
|
||||
struct grouphead *g_link; /* Next grouphead in list */
|
||||
char *g_name; /* Name of this group */
|
||||
struct group *g_list; /* Users in group. */
|
||||
};
|
||||
|
||||
struct smopts_s {
|
||||
struct smopts_s *s_link; /* Link to next smopts_s in list */
|
||||
char *s_name; /* Name of this smopts_s */
|
||||
struct name *s_smopts; /* sendmail options name list */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of the hash table of ignored header fields
|
||||
*/
|
||||
struct ignoretab {
|
||||
size_t i_count; /* Number of entries */
|
||||
struct ignore {
|
||||
struct ignore *i_link; /* Next ignored field in bucket */
|
||||
char *i_field; /* This ignored field */
|
||||
} *i_head[HSHSIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* Constants for conditional commands. These control whether we
|
||||
* should be executing commands or not.
|
||||
*/
|
||||
struct cond_stack_s {
|
||||
struct cond_stack_s *c_next;
|
||||
int c_cond;
|
||||
};
|
||||
#define CNONE 0x00 /* Execute everything */
|
||||
#define CSKIP 0x01 /* Do not execute commands */
|
||||
#define CIF 0x02 /* Inside if/endif block */
|
||||
#define CELSE 0x04 /* The last conditional was else */
|
||||
#define CIGN 0x08 /* Conditional in a skipped block */
|
||||
|
||||
enum mailmode_e {
|
||||
mm_receiving, /* receiving mail mode */
|
||||
mm_sending, /* sending mail mode */
|
||||
mm_hdrsonly /* headers only mode */
|
||||
};
|
||||
|
||||
/*
|
||||
* Truncate a file to the last character written. This is
|
||||
* useful just before closing an old file that was opened
|
||||
* for read/write.
|
||||
*/
|
||||
#define trunc(stream) { \
|
||||
(void)fflush(stream); \
|
||||
(void)ftruncate(fileno(stream), (off_t)ftell(stream)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* White Space (WSP) as specified in see RFC 2822.
|
||||
*
|
||||
* NOTE: Use this in place of isblank() so it is inline. Also, unlike
|
||||
* the table implemented ctype(3) routines, this does not have input
|
||||
* range issues caused by sign extensions.
|
||||
*
|
||||
* See mime_header.h for the related is_FWS().
|
||||
*/
|
||||
static inline int
|
||||
is_WSP(int c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
static inline char *
|
||||
skip_WSP(const char *cp)
|
||||
{
|
||||
while (is_WSP(*cp))
|
||||
cp++;
|
||||
return __UNCONST(cp);
|
||||
}
|
||||
|
||||
static inline char *
|
||||
skip_space(char *p)
|
||||
{
|
||||
while (isspace((unsigned char)*p))
|
||||
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__ */
|
||||
365
usr.bin/mail/extern.h
Normal file
365
usr.bin/mail/extern.h
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
/* $NetBSD: extern.h,v 1.33 2014/12/16 19:30:24 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 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.
|
||||
*
|
||||
* @(#)extern.h 8.2 (Berkeley) 4/20/95
|
||||
* $NetBSD: extern.h,v 1.33 2014/12/16 19:30:24 christos Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EXTERN_H__
|
||||
#define __EXTERN_H__
|
||||
|
||||
/*
|
||||
* from cmd1.c
|
||||
*/
|
||||
int More(void *);
|
||||
int Type(void *);
|
||||
int folders(void *);
|
||||
int from(void *);
|
||||
int headers(void *);
|
||||
int inc(void *);
|
||||
int mboxit(void *);
|
||||
int more(void *);
|
||||
int pcmdlist(void *);
|
||||
int pdot(void *);
|
||||
int pipecmd(void *);
|
||||
int scroll(void *);
|
||||
int stouch(void *);
|
||||
int top(void *);
|
||||
int type(void *);
|
||||
#ifdef MIME_SUPPORT
|
||||
int page(void *);
|
||||
int Page(void *);
|
||||
int print(void *);
|
||||
int Print(void *);
|
||||
int view(void *);
|
||||
int View(void *);
|
||||
#endif
|
||||
/* XXX - should these be elsewhere? */
|
||||
void printhead(int);
|
||||
char * sget_msgnum(struct message *, struct message *);
|
||||
void show_msgnum(FILE *, struct message *, struct message *);
|
||||
|
||||
/*
|
||||
* from cmd2.c
|
||||
*/
|
||||
int Detach(void *);
|
||||
int Save(void *);
|
||||
int clobber(void *);
|
||||
int copycmd(void *);
|
||||
int core(void *);
|
||||
int delete(void *);
|
||||
int deltype(void *);
|
||||
int detach(void *);
|
||||
int igfield(void *);
|
||||
int next(void *);
|
||||
int retfield(void *);
|
||||
int save(void *);
|
||||
int saveigfield(void *);
|
||||
int saveretfield(void *);
|
||||
int swrite(void *);
|
||||
int undeletecmd(void *);
|
||||
|
||||
/*
|
||||
* from cmd3.c
|
||||
*/
|
||||
int Respond(void *);
|
||||
int alternates(void *);
|
||||
int bounce(void *);
|
||||
int dosh(void *);
|
||||
int echo(void *);
|
||||
int elsecmd(void *);
|
||||
int endifcmd(void *);
|
||||
int file(void *);
|
||||
int bounce(void *);
|
||||
int forward(void *);
|
||||
int group(void *);
|
||||
int help(void *);
|
||||
int ifcmd(void *);
|
||||
int ifdefcmd(void *v);
|
||||
int ifndefcmd(void *v);
|
||||
int markread(void *);
|
||||
int messize(void *);
|
||||
int null(void *);
|
||||
int preserve(void *);
|
||||
int respond(void *);
|
||||
int rexit(void *);
|
||||
int schdir(void *);
|
||||
int set(void *);
|
||||
int shell(void *);
|
||||
int show(void *);
|
||||
int unalias(void *);
|
||||
int unread(void *);
|
||||
int unset(void *);
|
||||
/* XXX - Should this be elsewhere? */
|
||||
void sort(const char **);
|
||||
|
||||
/*
|
||||
* from cmd4.c
|
||||
*/
|
||||
struct smopts_s *findsmopts(const char *, int);
|
||||
int smoptscmd(void *);
|
||||
int unsmoptscmd(void *);
|
||||
int Header(void *);
|
||||
|
||||
/*
|
||||
* from cmdtab.c
|
||||
*/
|
||||
extern const struct cmd cmdtab[];
|
||||
|
||||
/*
|
||||
* from collect.c
|
||||
*/
|
||||
FILE * collect(struct header *, int);
|
||||
void savedeadletter(FILE *);
|
||||
|
||||
/*
|
||||
* from dotlock.c
|
||||
*/
|
||||
int dot_lock(const char *, int, FILE *, const char *);
|
||||
void dot_unlock(const char *);
|
||||
|
||||
/*
|
||||
* from edit.c
|
||||
*/
|
||||
int editor(void *);
|
||||
int visual(void *);
|
||||
FILE * run_editor(FILE *, off_t, int, int);
|
||||
|
||||
/*
|
||||
* from fio.c
|
||||
*/
|
||||
const char *expand(const char *);
|
||||
off_t fsize(FILE *);
|
||||
const char *getdeadletter(void);
|
||||
int getfold(char *, size_t);
|
||||
#ifdef USE_EDITLINE
|
||||
#define readline xreadline /* readline() is defined in libedit */
|
||||
#endif
|
||||
int readline(FILE *, char *, int, int);
|
||||
int putline(FILE *, const char *, int);
|
||||
int rm(char *);
|
||||
FILE * setinput(const struct message *);
|
||||
void setptr(FILE *, off_t);
|
||||
|
||||
/*
|
||||
* from getname.c
|
||||
*/
|
||||
const char *getname(uid_t);
|
||||
int getuserid(char []);
|
||||
|
||||
/*
|
||||
* from head.c
|
||||
*/
|
||||
int ishead(const char []);
|
||||
void parse(const char [], struct headline *, char []);
|
||||
|
||||
/*
|
||||
* from lex.c
|
||||
*/
|
||||
void announce(void);
|
||||
void commands(void);
|
||||
enum execute_contxt_e { ec_normal, ec_composing, ec_autoprint };
|
||||
int execute(char [], enum execute_contxt_e);
|
||||
int incfile(void);
|
||||
const struct cmd *lex(char []);
|
||||
void load(const char *);
|
||||
int newfileinfo(int);
|
||||
int pversion(void *);
|
||||
int setfile(const char *);
|
||||
char * shellpr(char *);
|
||||
char * get_cmdname(char *);
|
||||
|
||||
/*
|
||||
* from list.c
|
||||
*/
|
||||
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) __dead;
|
||||
|
||||
/*
|
||||
* from main.c
|
||||
*/
|
||||
struct name *lexpand(char *, int);
|
||||
void setscreensize(void);
|
||||
int main(int, char **);
|
||||
|
||||
/*
|
||||
* from names.c
|
||||
*/
|
||||
struct name *cat(struct name *, struct name *);
|
||||
int count(struct name *);
|
||||
struct name *delname(struct name *, char []);
|
||||
char * detract(struct name *, int);
|
||||
struct name * elide(struct name *);
|
||||
struct name * extract(char [], int);
|
||||
struct name * gexpand(struct name *, struct grouphead *, int, int);
|
||||
struct name * nalloc(char [], int);
|
||||
struct name * outof(struct name *, FILE *, struct header *);
|
||||
const char ** unpack(struct name *, struct name *);
|
||||
struct name * usermap(struct name *);
|
||||
#if 0
|
||||
void prettyprint(struct name *); /* commented out? */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* from popen.c
|
||||
*/
|
||||
int Fclose(FILE *);
|
||||
FILE * Fdopen(int, const char *);
|
||||
FILE * Fopen(const char *, const char *);
|
||||
int Pclose(FILE *);
|
||||
FILE * Popen(const char *, const char *);
|
||||
void close_all_files(void);
|
||||
void close_top_files(FILE *);
|
||||
void free_child(int);
|
||||
void prepare_child(sigset_t *, int, int);
|
||||
FILE * last_registered_file(int);
|
||||
void register_file(FILE *, int, int);
|
||||
int run_command(const char *, sigset_t *, int, int, ...);
|
||||
void sigchild(int);
|
||||
int start_command(const char *, sigset_t *, int, int, ...);
|
||||
int wait_child(int);
|
||||
#ifdef MIME_SUPPORT
|
||||
void flush_files(FILE *, int);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* from quit.c
|
||||
*/
|
||||
void quit(jmp_buf);
|
||||
int quitcmd(void *);
|
||||
|
||||
/*
|
||||
* from send.c
|
||||
*/
|
||||
#ifndef MIME_SUPPORT
|
||||
# define sendmessage(a,b,c,d,e) legacy_sendmessage(a,b,c,d)
|
||||
# define mail(a,b,c,d,e,f) legacy_mail(a,b,c,d,e)
|
||||
#endif
|
||||
int sendmessage(struct message *, FILE *, struct ignoretab *, const char *, struct mime_info *);
|
||||
int mail(struct name *, struct name *, struct name *, struct name *, char *, struct attachment *);
|
||||
void mail1(struct header *, int);
|
||||
void mail2(FILE *, const char **);
|
||||
int puthead(struct header *, FILE *, int);
|
||||
int sendmail(void *);
|
||||
|
||||
/*
|
||||
* from strings.c
|
||||
*/
|
||||
void * csalloc(size_t, size_t);
|
||||
void * salloc(size_t);
|
||||
void sreset(void);
|
||||
void spreserve(void);
|
||||
|
||||
/*
|
||||
* from support.c
|
||||
*/
|
||||
void add_ignore(const char *, struct ignoretab *);
|
||||
void alter(char *);
|
||||
int argcount(char **);
|
||||
int blankline(char []);
|
||||
char * copy(char *, char *);
|
||||
char * hfield(const char [], const struct message *);
|
||||
int isdir(const char []);
|
||||
int isign(const char *, struct ignoretab []);
|
||||
void istrcpy(char *, const char *);
|
||||
int member(char *, struct ignoretab *);
|
||||
char * nameof(struct message *, int);
|
||||
int sasprintf(char **ret, const char *format, ...) __printflike(2, 3);
|
||||
char * savestr(const char *);
|
||||
struct message *set_m_flag(int, int, int);
|
||||
char * skin(char *);
|
||||
int source(void *);
|
||||
void touch(struct message *);
|
||||
int unstack(void);
|
||||
int upcase(int);
|
||||
void cathelp(const char *);
|
||||
|
||||
/*
|
||||
* from temp.c
|
||||
*/
|
||||
void tinit(void);
|
||||
|
||||
/*
|
||||
* from tty.c
|
||||
*/
|
||||
int grabh(struct header *, int);
|
||||
|
||||
/*
|
||||
* from vars.c
|
||||
*/
|
||||
void assign(const char [], const char []);
|
||||
struct grouphead * findgroup(const char []);
|
||||
int hash(const char *);
|
||||
struct var * lookup(const char []);
|
||||
void printgroup(const char []);
|
||||
void v_free(char *);
|
||||
char * value(const char []);
|
||||
char * vcopy(const char []);
|
||||
|
||||
/*
|
||||
* from v7.local.c
|
||||
*/
|
||||
void demail(void);
|
||||
void findmail(const char *, char *, size_t);
|
||||
const char *username(void);
|
||||
|
||||
/*
|
||||
* from version.c
|
||||
*/
|
||||
extern const char *version;
|
||||
|
||||
|
||||
#ifndef THREAD_SUPPORT
|
||||
/*
|
||||
* Specials from fio.c (if THREAD_SUPPORT is not defined).
|
||||
* With THREAD_SUPPORT, they live in thread.c.
|
||||
*/
|
||||
struct message *next_message(struct message *);
|
||||
struct message *prev_message(struct message *);
|
||||
struct message *get_message(int);
|
||||
int get_msgnum(struct message *);
|
||||
int get_msgCount(void);
|
||||
|
||||
/* we remap these commands */
|
||||
# define get_abs_msgCount get_msgCount
|
||||
# define get_abs_message(a) get_message(a)
|
||||
# define next_abs_message(a) next_message(a)
|
||||
|
||||
/* we trash these commands */
|
||||
# define do_recursion() 0
|
||||
# define thread_recursion(mp,fn,args) fn(mp,args)
|
||||
# define thread_fix_old_links(nmessage,message,omsgCount)
|
||||
# define thread_fix_new_links(message,omsgCount,msgCount)
|
||||
#endif /* THREAD_SUPPORT */
|
||||
|
||||
#endif /* __EXTERN_H__ */
|
||||
289
usr.bin/mail/head.c
Normal file
289
usr.bin/mail/head.c
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/* $NetBSD: head.c,v 1.24 2013/01/16 15:21:42 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 4/20/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: head.c,v 1.24 2013/01/16 15:21:42 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include "rcv.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* Mail -- a mail program
|
||||
*
|
||||
* Routines for processing and detecting headlines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Match the given string (cp) against the given template (tp).
|
||||
* Return 1 if they match, 0 if they don't
|
||||
*/
|
||||
static int
|
||||
cmatch(const char *cp, const char *tp)
|
||||
{
|
||||
|
||||
while (*cp && *tp)
|
||||
switch (*tp++) {
|
||||
case 'a':
|
||||
if (!islower((unsigned char)*cp++))
|
||||
return 0;
|
||||
break;
|
||||
case 'A':
|
||||
if (!isupper((unsigned char)*cp++))
|
||||
return 0;
|
||||
break;
|
||||
case ' ':
|
||||
if (*cp++ != ' ')
|
||||
return 0;
|
||||
break;
|
||||
case '0':
|
||||
if (!isdigit((unsigned char)*cp++))
|
||||
return 0;
|
||||
break;
|
||||
case 'O':
|
||||
if (*cp != ' ' && !isdigit((unsigned char)*cp))
|
||||
return 0;
|
||||
cp++;
|
||||
break;
|
||||
case ':':
|
||||
if (*cp++ != ':')
|
||||
return 0;
|
||||
break;
|
||||
case 'N':
|
||||
if (*cp++ != '\n')
|
||||
return 0;
|
||||
break;
|
||||
case '+':
|
||||
if (*cp != '+' && *cp != '-')
|
||||
return 0;
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
if (*cp || *tp)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test to see if the passed string is a ctime(3) generated
|
||||
* date string as documented in the manual. The template
|
||||
* below is used as the criterion of correctness.
|
||||
* Also, we check for a possible trailing time zone using
|
||||
* the tmztype template.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 'A' An upper case char
|
||||
* 'a' A lower case char
|
||||
* ' ' A space
|
||||
* '0' A digit
|
||||
* 'O' An optional digit or space
|
||||
* ':' A colon
|
||||
* 'N' A new line
|
||||
* '+' A plus or minus sign
|
||||
*/
|
||||
static struct cmatch_data {
|
||||
size_t tlen;
|
||||
char const *tdata;
|
||||
} const cmatch_data[] = {
|
||||
#define TSZ(a) (sizeof(a) - 1), a
|
||||
{ TSZ("Aaa Aaa O0 00:00:00 0000") }, /* BSD ctype */
|
||||
{ TSZ("Aaa Aaa O0 00:00 0000") }, /* SysV ctype */
|
||||
{ TSZ("Aaa Aaa O0 00:00:00 AAA 0000") }, /* BSD tmztype */
|
||||
{ TSZ("Aaa Aaa O0 00:00 AAA 0000") }, /* SysV tmztype */
|
||||
/*
|
||||
* RFC 822-alike From_ lines do not conform to RFC 4155, but seem to
|
||||
* be used in the wild by UW-imap (MBX format plus)
|
||||
*/
|
||||
{ TSZ("Aaa Aaa O0 00:00:00 0000 +0000") }, /* RFC822, UT offset */
|
||||
/*
|
||||
* RFC 822 with zone spec:
|
||||
* 1. military,
|
||||
* 2. UT,
|
||||
* 3. north america time zone strings
|
||||
* note that 1. is strictly speaking not correct as some letters are
|
||||
* not used
|
||||
*/
|
||||
{ TSZ("Aaa Aaa O0 00:00:00 0000 A") },
|
||||
{ TSZ("Aaa Aaa O0 00:00:00 0000 AA") },
|
||||
{ TSZ("Aaa Aaa O0 00:00:00 0000 AAA") },
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
static int
|
||||
isdate(const char date[])
|
||||
{
|
||||
static size_t cmatch_minlen = 0;
|
||||
struct cmatch_data const *cmdp;
|
||||
size_t dl = strlen(date);
|
||||
|
||||
if (cmatch_minlen == 0)
|
||||
for (cmdp = cmatch_data; cmdp->tdata != NULL; ++cmdp)
|
||||
cmatch_minlen = MIN(cmatch_minlen, cmdp->tlen);
|
||||
|
||||
if (dl < cmatch_minlen)
|
||||
return 0;
|
||||
|
||||
for (cmdp = cmatch_data; cmdp->tdata != NULL; ++cmdp)
|
||||
if (dl == cmdp->tlen && cmatch(date, cmdp->tdata))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fail(const char linebuf[], const char reason[])
|
||||
{
|
||||
#ifndef FMT_PROG
|
||||
if (debug)
|
||||
(void)fprintf(stderr, "\"%s\"\nnot a header because %s\n",
|
||||
linebuf, reason);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect a liberal (space, tab delimited) word into the word buffer
|
||||
* passed. Also, return a pointer to the next word following that,
|
||||
* or NULL if none follow.
|
||||
*/
|
||||
static const char *
|
||||
nextword(const char *wp, char *wbuf)
|
||||
{
|
||||
if (wp == NULL) {
|
||||
*wbuf = 0;
|
||||
return NULL;
|
||||
}
|
||||
while (*wp && !is_WSP(*wp)) {
|
||||
*wbuf++ = *wp;
|
||||
if (*wp++ == '"') {
|
||||
while (*wp && *wp != '"')
|
||||
*wbuf++ = *wp++;
|
||||
if (*wp == '"')
|
||||
*wbuf++ = *wp++;
|
||||
}
|
||||
}
|
||||
*wbuf = '\0';
|
||||
wp = skip_WSP(wp);
|
||||
if (*wp == '\0')
|
||||
return NULL;
|
||||
return wp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the string on the left into the string on the right
|
||||
* and bump the right (reference) string pointer by the length.
|
||||
* Thus, dynamically allocate space in the right string, copying
|
||||
* the left string into it.
|
||||
*/
|
||||
static char *
|
||||
copyin(const char *src, char **space)
|
||||
{
|
||||
char *cp;
|
||||
char *begin;
|
||||
|
||||
begin = cp = *space;
|
||||
while ((*cp++ = *src++) != '\0')
|
||||
continue;
|
||||
*space = cp;
|
||||
return begin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split a headline into its useful components.
|
||||
* Copy the line into dynamic string space, then set
|
||||
* pointers into the copied line in the passed headline
|
||||
* structure. Actually, it scans.
|
||||
*
|
||||
* XXX - line[], pbuf[], and word[] must be LINESIZE in length or
|
||||
* overflow can occur in nextword() or copyin().
|
||||
*/
|
||||
PUBLIC void
|
||||
parse(const char line[], struct headline *hl, char pbuf[])
|
||||
{
|
||||
const char *cp;
|
||||
char *sp;
|
||||
char word[LINESIZE];
|
||||
|
||||
hl->l_from = NULL;
|
||||
hl->l_tty = NULL;
|
||||
hl->l_date = NULL;
|
||||
cp = line;
|
||||
sp = pbuf;
|
||||
/*
|
||||
* Skip over "From" first.
|
||||
*/
|
||||
cp = nextword(cp, word);
|
||||
cp = nextword(cp, word);
|
||||
if (*word)
|
||||
hl->l_from = copyin(word, &sp);
|
||||
if (cp != NULL && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') {
|
||||
cp = nextword(cp, word);
|
||||
hl->l_tty = copyin(word, &sp);
|
||||
}
|
||||
if (cp != NULL)
|
||||
hl->l_date = copyin(cp, &sp);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the passed line buffer is a mail header.
|
||||
* Return true if yes. Note the extreme pains to
|
||||
* accommodate all funny formats.
|
||||
*/
|
||||
PUBLIC int
|
||||
ishead(const char linebuf[])
|
||||
{
|
||||
const char *cp;
|
||||
struct headline hl;
|
||||
char parbuf[LINESIZE];
|
||||
|
||||
cp = linebuf;
|
||||
if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' ||
|
||||
*cp++ != ' ')
|
||||
return 0;
|
||||
parse(linebuf, &hl, parbuf);
|
||||
if (hl.l_from == NULL || hl.l_date == NULL) {
|
||||
fail(linebuf, "No from or date field");
|
||||
return 0;
|
||||
}
|
||||
if (!isdate(hl.l_date)) {
|
||||
fail(linebuf, "Date field not legal date");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* I guess we got it!
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
49
usr.bin/mail/pathnames.h
Normal file
49
usr.bin/mail/pathnames.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* $NetBSD: pathnames.h,v 1.8 2006/11/28 18:45:32 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 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.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
|
||||
* $NetBSD: pathnames.h,v 1.8 2006/11/28 18:45:32 christos Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PATHNAMES_H__
|
||||
#define __PATHNAMES_H__
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_EX "/usr/bin/ex"
|
||||
#define _PATH_HELP "/usr/share/misc/mail.help"
|
||||
#define _PATH_TILDE "/usr/share/misc/mail.tildehelp"
|
||||
#define _PATH_MASTER_RC "/etc/mail.rc"
|
||||
#define _PATH_MORE "/usr/bin/more"
|
||||
#ifdef MIME_SUPPORT
|
||||
#define _PATH_FILE "/usr/bin/file" /* Used to get mime type/subtype */
|
||||
#endif
|
||||
|
||||
#endif /* __PATHNAMES_H__ */
|
||||
48
usr.bin/mail/rcv.h
Normal file
48
usr.bin/mail/rcv.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* $NetBSD: rcv.h,v 1.7 2006/11/28 18:45:32 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.
|
||||
*
|
||||
* @(#)rcv.h 8.1 (Berkeley) 6/6/93
|
||||
* $NetBSD: rcv.h,v 1.7 2006/11/28 18:45:32 christos Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Mail -- a mail program
|
||||
*
|
||||
* This file is included by normal files which want both
|
||||
* globals and declarations.
|
||||
*/
|
||||
|
||||
#ifndef __RCV_H__
|
||||
#define __RCV_H__
|
||||
|
||||
#include "def.h"
|
||||
#include "glob.h"
|
||||
|
||||
#endif /* __RCV_H__ */
|
||||
Loading…
Reference in New Issue
Block a user