/***********************************************************************
* *
* This software is part of the BSD package *
*Copyright (c) 1978-2006 The Regents of the University of California an*
* *
* 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 *
* materials provided with the distribution. *
* *
* 3. Neither the name of The Regents of the University of California*
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. *
* *
* 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 *
* 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. *
* *
* Kurt Shoens (UCB) *
* gsf *
* *
***********************************************************************/
#pragma prototyped
/*
* Mail -- a mail program
*
* Collect input from standard input, handling ~ escapes.
*/
#include "mailx.h"
#define PART_INIT 0
/*
* On interrupt, come here to save the partial message in ~/dead.letter.
* Then jump out of the collection loop.
*/
/*ARGSUSED*/
static void
{
/*
* the control flow is subtle, because we can be called from ~q.
*/
puts("@");
return;
}
}
}
/*ARGSUSED*/
static void
{
/*
* Let's pretend nobody else wants to clean up,
* a true statement at this time.
*/
exit(1);
}
/*
* Print (continue) when continued after ^Z.
*/
/*ARGSUSED*/
static void
{
}
}
/*
* Write a file, ex-like if f set.
*/
static int
{
if (f)
if (!f)
note(0, "[File exists]");
return -1;
}
return -1;
return -1;
}
return 0;
}
/*
* Edit the message on state.collect.fp.
* On return, make the edit file the new temp file.
*/
static void
{
}
}
/*
* Pipe the message through the command.
* Old message is on stdin of command;
* New message collected from stdout.
* Sh -c must return 0 to accept the new message.
*/
static void
{
goto out;
/*
* stdin = current message.
* stdout = new message.
*/
goto out;
}
goto out;
}
/*
* Take new files.
*/
out:
}
/*
* Return the name of the dead.letter file.
*/
static char*
deadletter(void)
{
register char* s;
}
return s;
}
/*
* Interpolate the named messages into the current
* message, preceding each line with a tab.
* Return a count of the number of characters now in
* the message, or -1 if an error is encountered writing
* the message temporary. The flag argument is 'm' if we
* should shift over and 'f' if not.
*/
static int
{
char* prefix;
unsigned long flags;
if (getmsglist(ms, 0) < 0)
return 0;
note(0, "No appropriate messages");
return 0;
}
}
flags = 0;
if (f == 'f' || f == 'F') {
if (f == 'f')
prefix = 0;
}
prefix = "\t";
if (!followup)
printf("Interpolating:");
if (followup)
flags |= GREFERENCES;
else
return -1;
}
}
if (!followup)
printf("\n");
return 0;
}
/*
* Generate multipart boundary.
*/
void
boundary(void)
{
state.part.out.boundlen = sfsprintf(state.part.out.boundary, sizeof(state.part.out.boundary), "=_=_=_=_=%s==%04X==%08X==", state.var.user, getpid(), time(NiL));
}
}
/*
* Ouput multipart header.
*/
static void
{
char* s;
name = s + 1;
boundary();
if (!type)
if (name)
fprintf(fp, "\nContent-Transfer-Encoding: %s\n", (code & CODE_64) ? "base64" : (code & CODE_QP) ? "quoted-printable" : "7bit");
if (name)
}
/*
* Collect input from standard input, handling ~ escapes.
*/
FILE*
{
register char* s;
register int n;
int ask;
int c;
int eofcount;
int escape;
int headers;
int code;
int sig;
int g;
long cc;
long lc;
long tc;
char* t;
char* e;
ask = 0;
headers = 0;
/*
* Start catching signals from here, but we'll still die on interrupts
* until we're in the main loop.
*/
#ifdef SIGTSTP
#endif
#ifdef SIGTTOU
#endif
#ifdef SIGTTIN
#endif
goto err;
}
goto err;
goto err;
note(0, "(continue)");
}
else {
headers = 1;
g &= ~GNL;
}
g &= ~GNL;
}
g |= GREFERENCES;
}
if (headers)
}
eofcount = 0;
/*
* Come here for printing the after-signal message.
* Duplicate messages won't be printed because
* the write is aborted if we get a SIGTTOU.
*/
cont:
note(0, "\n(Interrupt -- one more to kill letter)");
else
note(0, "(continue)");
}
else if (ask)
for (;;) {
if (headers) {
continue;
headers = 0;
}
if (c < 0) {
note(0, "Use \".\" to terminate letter");
continue;
}
break;
}
eofcount = 0;
break;
goto err;
continue;
}
switch (c) {
case '!':
/*
* Shell escape, send the balance of the
* line to sh -c.
*/
break;
case '.':
/*
* Simulate end of file on input.
*/
goto out;
case ':':
case '_':
/*
* Escape to command mode, but be nice!
*/
goto cont;
case '?':
av[1] = 0;
break;
case 'A':
case 'a':
/*
* Sign letter.
*/
if (s)
goto outstr;
filecopy(state.var.signature, fp, state.var.signature, state.collect.fp, stdout, (off_t)0, NiL, NiL, 0);
}
goto cont;
case 'b':
/*
* Add stuff to blind carbon copies list.
*/
break;
case 'c':
/*
* Add to the CC list.
*/
break;
case 'd':
/* fall into . . . */
case 'g':
case 'r':
case '<':
/*
* Invoke a file:
* Search for the file name,
* then open it and copy the contents
* to state.collect.fp.
*/
if (!*s || !(s = expand(s, 1))) {
note(0, "Read what file !?");
break;
}
if (c == 'g') {
break;
code = 0;
if (mime(1)) {
}
else
t = 0;
tc++;
cc++;
}
else {
if (t) {
t = 0;
}
else {
}
}
else
t = s;
}
else
t = s;
if (t)
{
}
break;
}
}
break;
lc = 0;
cc = 0;
lc++;
goto err;
}
cc += n;
}
if (c == 'g')
break;
case 'e':
case 'v':
/*
* Edit the current message.
* 'e' means to use EDITOR
* 'v' means to use VISUAL
*/
editmessage(hp, c);
goto cont;
case 'f':
case 'F':
case 'm':
case 'M':
/*
* Interpolate the named messages, if we
* are in receiving mail mode. Does the
* standard list processing garbage.
* If ~f is given, we don't shift over.
*/
goto err;
goto cont;
case 'h':
/*
* Grab the standard headers.
*/
goto cont;
case 'i':
/*
* Insert variable value.
*/
s = varget(s);
if (s) {
}
goto cont;
case 'p':
/*
* Print out the current state of the
* message without altering anything.
*/
else {
lc -= 5;
if (c == '\n' && --lc <= 0) {
break;
}
}
}
goto cont;
case 's':
/*
* Set the Subject list.
*/
while (isspace(*s))
s++;
break;
case 't':
/*
* Add to the To list.
*/
break;
case 'w':
/*
* Write the message on a file.
*/
while (*s == ' ' || *s == '\t')
s++;
if (*s == 0) {
note(0, "Write what file !?");
break;
}
if (!(s = expand(s, 1)))
break;
break;
case 'x':
/*FALLTHROUGH*/
case 'q':
/*
* Force a quit of sending mail.
* Act like an interrupt happened.
*/
exit(1);
case '|':
/*
* Pipe message through command.
* Collect output as new message.
*/
goto cont;
default:
/*
* On double escape, just send the single one.
* Otherwise, it's an error.
*/
if (c == escape) {
goto err;
else
break;
}
if (isprint(c))
else
break;
}
}
goto out;
err:
}
out:
/*
* Copy to a temp file adding the mime boundaries.
*/
n = PART_INIT;
if (s[0] == '-' && s[1] == '-' && !strncmp(s + 2, state.part.out.boundary, state.part.out.boundlen)) {
if (n == PART_INIT)
if (*t == '\n' || *t == '\r' && *(t + 1) == '\n')
n = PART_DATA;
else if (*t++ == '-' && *t++ == '-' && (*t == '\n' || *t == '\r' && *(t + 1) == '\n')) {
n = PART_INIT;
continue;
}
}
else if (n == PART_INIT) {
if (*s == '\n' || *s == '\r' && *(s + 1) == '\n')
continue;
n = PART_MAIN;
}
}
}
}
}
#ifdef SIGTSTP
#endif
#ifdef SIGTTOU
#endif
#ifdef SIGTTIN
#endif
}
/*
* Save fp in ${DEAD}.
*/
void
{
char* s;
}
}