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:
David van Moolenbroek 2017-02-20 15:56:15 +00:00
parent 045e0ed35c
commit 5ae330e220
13 changed files with 2002 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__ */