]> Zhao Yanbai Git Server - minix.git/commitdiff
Import NetBSD fmt(1) 03/3403/1
authorDavid van Moolenbroek <david@minix3.org>
Mon, 20 Feb 2017 15:56:15 +0000 (15:56 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 22 Feb 2017 17:18:00 +0000 (17:18 +0000)
This requires importing a few files from mail(1) already.  Importing
the rest of mail(1) is left to future work.

Change-Id: If96513a306245cd7fb64660758d0dbd29a36e87c

13 files changed:
distrib/sets/lists/minix-base/mi
distrib/sets/lists/minix-debug/mi
distrib/sets/lists/minix-man/mi
usr.bin/Makefile
usr.bin/fmt/Makefile [new file with mode: 0644]
usr.bin/fmt/buffer.h [new file with mode: 0644]
usr.bin/fmt/fmt.1 [new file with mode: 0644]
usr.bin/fmt/fmt.c [new file with mode: 0644]
usr.bin/mail/def.h [new file with mode: 0644]
usr.bin/mail/extern.h [new file with mode: 0644]
usr.bin/mail/head.c [new file with mode: 0644]
usr.bin/mail/pathnames.h [new file with mode: 0644]
usr.bin/mail/rcv.h [new file with mode: 0644]

index 116256723e7a34e062ae67333c346f0a2434e68f..67ae9e428465ac3a46b2d6d9cbd2dc753db7f42e 100644 (file)
 ./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
index be5e6ee075423fca7021ac113a5d723e7c8174b8..99dd9fb3abd077120bf5fe2a3aea239487a65e09 100644 (file)
 ./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
index 17122db7849163b0cdb6cca757eade4fdf445fda..3c349835bb7178b82d2bc9c3202bdfe9b1618b17 100644 (file)
 ./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
index c397185d26b7376161a1020a5f197277b934bf82..e9528ee531c55899ca602dc8838c82c8babe83a9 100644 (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 \
diff --git a/usr.bin/fmt/Makefile b/usr.bin/fmt/Makefile
new file mode 100644 (file)
index 0000000..a794cb1
--- /dev/null
@@ -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>
diff --git a/usr.bin/fmt/buffer.h b/usr.bin/fmt/buffer.h
new file mode 100644 (file)
index 0000000..41016e4
--- /dev/null
@@ -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';
+}
diff --git a/usr.bin/fmt/fmt.1 b/usr.bin/fmt/fmt.1
new file mode 100644 (file)
index 0000000..623b124
--- /dev/null
@@ -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.
diff --git a/usr.bin/fmt/fmt.c b/usr.bin/fmt/fmt.c
new file mode 100644 (file)
index 0000000..c420b26
--- /dev/null
@@ -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';
+}
diff --git a/usr.bin/mail/def.h b/usr.bin/mail/def.h
new file mode 100644 (file)
index 0000000..f43e205
--- /dev/null
@@ -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__ */
diff --git a/usr.bin/mail/extern.h b/usr.bin/mail/extern.h
new file mode 100644 (file)
index 0000000..95dee15
--- /dev/null
@@ -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__ */
diff --git a/usr.bin/mail/head.c b/usr.bin/mail/head.c
new file mode 100644 (file)
index 0000000..bdb5962
--- /dev/null
@@ -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;
+}
diff --git a/usr.bin/mail/pathnames.h b/usr.bin/mail/pathnames.h
new file mode 100644 (file)
index 0000000..6866f6d
--- /dev/null
@@ -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__ */
diff --git a/usr.bin/mail/rcv.h b/usr.bin/mail/rcv.h
new file mode 100644 (file)
index 0000000..e49dbed
--- /dev/null
@@ -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__ */