/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2014 Joyent, Inc.
*/
/*
* Copyright 1999 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include "rcv.h"
#include <locale.h>
#include <wordexp.h>
/*
* mailx -- a modified version of a University of California at Berkeley
* mail program
*
* File I/O.
*/
/*
* Set up the input pointers while copying the mail file into
* /tmp.
*/
void
{
int hdr = 0;
register char *cp;
register int l;
register long s;
short flag;
if (!space) {
msgCount = 0;
offset = 0;
space = 32;
newmail = 0;
message =
"calloc: insufficient memory for %d messages\n"),
space);
exit(1);
/* NOTREACHED */
}
} else {
newmail = 1;
}
s = 0L;
l = 0;
/*
* Set default flags. When reading from
* a folder, assume the message has been
* previously read.
*/
if (edit)
else
inhead = 0;
if (!newline) {
goto putout;
}
top:
/*
* NB: this only can happen if there is a
* small content that is NOT \n terminated
* and has no leading blank line, i.e., never.
*/
clen) {
} else {
}
s += clen;
n -= (int)clen;
/* shift line to the left, copy null as well */
cflg = 0;
blankline = 1;
StartNewMsg = TRUE;
goto top;
}
/* here, clen == 0 or clen >= n */
/* leading empty line */
clen++; /* cheat */
inhead = 0;
}
s += (long)clen;
for (;;) {
} else {
}
clen -= n;
if (clen <= 0) {
break;
}
"%s:\tYour mailfile was found to be corrupted.\n"),
progname);
"\t(Unexpected end-of-file).\n"));
"\tMessage #%d may be truncated.\n\n"),
msgCount);
s -= clen;
clen = 0; /* stop the loop */
}
}
/* All done, go to top for next message */
cflg = 0;
blankline = 1;
StartNewMsg = TRUE;
continue;
}
/* Look for a From line that starts a new message */
}
/*
* Limit the speed at which the
* allocated space grows.
*/
if (space < 512)
else
space += 512;
errno = 0;
perror("realloc failed");
"realloc: insufficient memory for %d messages\n"),
space);
exit(1);
}
}
newmail = 0;
msgCount++;
if (edit)
else
inhead = 1;
s = 0L;
l = 0;
StartNewMsg = FALSE;
goto putout;
}
/* if didn't get a header line, we're no longer in the header */
if (!hdr)
inhead = 0;
if (!inhead)
goto putout;
/*
* Look for Status: line. Do quick check for second character,
* many headers start with "S" but few have "t" as second char.
*/
}
/*
* Look for Content-Length and Content-Type headers. Like
* above, do a quick check for the "-", which is rare.
*/
if (!cflg) {
}
char *cp2;
*cp2 = '\0';
}
}
offset += n;
s += (long)n;
} else {
l++;
}
perror("/tmp");
exit(1);
}
if (msgCount == 0) {
}
newline = 1;
if (n == 1) {
/* Blank line. Skip StartNewMsg check below */
continue;
}
} else {
newline = 0;
}
if (StartNewMsg && !ToldUser) {
"%s:\tYour mailfile was found to be corrupted\n"),
progname);
gettext("\t(Content-length mismatch).\n"));
"\tMessage #%d may be truncated,\n"), msgCount);
"\twith another message concatenated to it.\n\n"));
}
}
if (n == 0) {
perror("/tmp");
exit(1);
}
if (msgCount) {
}
}
}
/*
* Compute the content length of a message and set it into m_clen.
*/
void
{
long c;
fline = 1;
while (c > 0L) {
c -= nread;
/*
* First line is the From line, so no headers
* there to worry about.
*/
if (fline) {
fline = 0;
continue;
}
/*
* If line is blank, we've reached end of headers.
*/
if (line[0] == '\n')
break;
/*
* If this line is a continuation
* of a previous header field, keep going.
*/
continue;
/*
* If we are no longer looking at real
* header lines, we're done.
* This happens in uucp style mail where
* there are no headers at all.
*/
c += nread;
break;
}
}
if (c == 0)
c = 1;
}
static int
{
register int c;
if ((*cp++ = (char)c) == '\n')
break;
*cp = '\0';
}
/*
* Read up a line from the specified input into the line
* buffer. Return the number of characters read. Do not
* include the newline at the end.
*/
int
{
register char *cp;
register int c;
int seennulls = 0;
if (c == 0) {
if (!seennulls) {
gettext("mailx: NUL changed to @\n"));
seennulls++;
}
c = '@';
}
*cp++ = (char)c;
}
*cp = 0;
return (0);
}
/*
* linecount - determine the number of lines in a printable file.
*/
static int
{
register int count;
count = 0;
if (*cp++ == '\n')
count++;
return (count);
}
/*
* Return a file buffer all ready to read up the
* passed message pointer.
*/
FILE *
{
perror("fseek");
panic("temporary file seek");
}
return (itf);
}
/*
* Delete a file, but only if the file is a plain file.
*/
int
{
extern int errno;
return (0); /* it's already gone, no error */
else
return (-1);
return (-1);
}
}
/*
* Terminate an editing session by attempting to write out the user's
* file from the temporary. Save any new stuff appended to the file.
*/
int
int noremove /* don't allow the file to be removed, trunc instead */
)
{
register int gotcha, c;
if (readonly)
return (0);
holdsigs();
}
}
gotcha++;
}
}
goto done;
relsesigs();
}
relsesigs();
}
relsesigs();
}
relsesigs();
}
}
if (tbuf)
relsesigs();
}
}
flush();
c = 0;
continue;
c++;
if (tbuf)
relsesigs();
}
}
}
relsesigs();
}
}
else
flush();
done:
relsesigs();
return (1);
}
#ifndef OLD_BSD_SIGS
#ifdef VMUNIX
static int omask = 0;
#else
#endif
#endif
/*
* Hold signals SIGHUP - SIGQUIT.
*/
void
holdsigs(void)
{
#ifndef OLD_BSD_SIGS
if (sigdepth++ == 0) {
#ifdef VMUNIX
#else
sigemptyset(&mask);
#endif
}
#else
#endif
}
/*
* Release signals SIGHUP - SIGQUIT
*/
void
relsesigs(void)
{
#ifndef OLD_BSD_SIGS
if (--sigdepth == 0)
#ifdef VMUNIX
#else
#endif
#else
#endif
}
#if !defined(OLD_BSD_SIGS) && !defined(VMUNIX)
void
{
return ((void (*)(int))-1);
return ((void (*)(int))osa.sa_handler);
}
#endif
/*
* Flush the standard output.
*/
void
flush(void)
{
}
/*
* Determine the size of the file possessed by
* the passed buffer.
*/
{
register int f;
return (0);
}
/*
* Check for either a stdio recognized error, or
* a possibly delayed write error (in case it's
* an NFS file, for instance).
*/
int
{
}
/*
* Take a file name, possibly with shell meta characters
* in it and expand it by using wordexp().
* Return the file name as a dynamic string.
* If the name cannot be expanded (for whatever reason)
* return NULL.
*/
char *
{
register char *cp;
register int l;
/* strip off trailing blanks */
cp--;
l = *++cp; /* save char */
*cp = '\0';
*cp = (char)l; /* restore char */
}
return (cp);
}
return (name);
}
return (NOSTR);
}
return (NOSTR);
}
}
/*
* Take a file name, possibly with shell meta characters
* in it and expand it by using "sh -c echo filename"
* Return the file name as a dynamic string.
* If the name cannot be expanded (for whatever reason)
* return the original file name.
*/
char *
{
}
/*
* Determine the current folder directory name.
*/
int
{
char *folder;
return (-1);
/*
* If name looks like a folder name, don't try
* to expand it, to prevent infinite recursion.
*/
*folder == '\0')
return (-1);
if (*folder == '/') {
} else
return (0);
}
/*
* A nicer version of Fdopen, which allows us to fclose
* without losing the open file.
*/
FILE *
{
register int f;
if (f < 0) {
perror("dup");
return (NULL);
}
}
/*
* return the filename associated with "s". This function always
* returns a non-null string (no error checking is done on the receiving end)
*/
char *
Getf(register char *s)
{
register char *cp;
return (safeexpand(cp));
} else if (strcmp(s, "MBOX") == 0) {
"mbox");
return (defbuf);
} else if (strcmp(s, "DEAD") == 0) {
"dead.letter");
return (defbuf);
} else if (strcmp(s, "MAILRC") == 0) {
".mailrc");
return (defbuf);
} else if (strcmp(s, "HOME") == 0) {
/* no recursion allowed! */
return (".");
}
return ("DEAD"); /* "cannot happen" */
}