Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

810 lines
22 KiB

/* send.c
*
* HISTORY:
* 10-Apr-87 danl Splitstr: new spec to handle case of only one token
* or very long token
* 11-Mar-87 danl Add pSep param to MakeAbortFile
* 10-Mar-87 danl Add tests for HDRRCD
* 10-Mar-87 danl Add SendIdoc
* 09-Apr-1987 mz Use whiteskip/whitescan
* 11-Apr-1987 mz Use PASCAL/INTERNAL
* 11-May-87 danl Bug fix: add return to ZMMakeStr in SortStr
* 15-May-87 danl AppendBody: Append trailing crlf so if sent to an
* email file, msgs are separated by blank line
* 11-Jun-87 danl SendIdoc: MailFile return zero/nonzero - not ERROR
* 20-Jun-87 danl ExpandHdrInfoAliases: move $rSTRING to strRcd
* 22-Jun-87 danl NotifyTools: add TOOLSINI
* 01-Jul-87 danl Use strWZMAIL
* 01-Jul-87 danl Get netstuff from ..\netstuff
* 14-Jul-87 danl Add SENDINI
* 15-Jul-87 danl Use fNotifyTools flags
* 23-Jul-87 danl Allow $t $c $b in alias expansion
* 05-Aug-87 danl Added pVecDL
* 06-Aug-87 danl GetHdrInfo: continue do not have to begin with whitespace
* 07-Aug-87 danl Change SortStr to UniqueStr
* 07-Aug-87 danl NotifyTools: count bytes in DefDir
* 12-Aug-87 danl Pass fpT to BytesDefDir
* 21-Aug-1987 mz Change references from MAXARG to MAXLINELEN
* 24-Sep-87 danl Look for TOOLS.INI not TOOLSINI as variable in tools.ini
* 04-Mar-88 danl Send Version msgs to wzmail not tools
* Add ifdef on SENDINI
* 16-Mar-88 danl use pToolsIni in swchng call
* 29-Apr-1988 mz Add WndPrintf
* Add PrintMsgList
* 12-Oct-1989 leefi v1.10.73, added inclusion of <string.h>
* 12-Oct-1989 leefi v1.10.73, clarified tmpfile error messages
*/
#define INCL_DOSINFOSEG
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\timeb.h>
#include <sys\stat.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "wzport.h"
#include <tools.h>
#include <ctype.h>
#include "dh.h"
#include "zm.h"
VOID PASCAL INTERNAL InitHdrInfo ( PHDRINFO pHdrInfo )
{
INT i;
PSTR *ppstr = NULL;
for ( ppstr = &(pHdrInfo->ppstr [ 0 ]), i = 0; i < CHDRFIELDS; i++ )
*ppstr++ = NULL;
pHdrInfo->lBody = pHdrInfo->lReplying = -1;
pHdrInfo->pstrRestOfHdr = AppendStr(NULL, strEMPTY, NULL, TRUE);
}
VOID PASCAL INTERNAL FreeHdrInfo ( PHDRINFO pHdrInfo, INT iHdr )
{
INT i;
PSTR *ppstr = NULL;
ppstr = pHdrInfo->ppstr;
if ( iHdr == HDRALL ) {
for ( i = 0; i < CHDRFIELDS; i++ ) {
ZMfree ( *ppstr );
*ppstr++ = NULL;
}
ZMfree(pHdrInfo->pstrRestOfHdr);
pHdrInfo->pstrRestOfHdr = NULL;
}
else {
ppstr += iHdr;
ZMfree ( *ppstr );
*ppstr = NULL;
}
}
PVECTOR PASCAL INTERNAL InsertVec ( PVECTOR pVec, PSTR pstr, FLAG fSorted )
{
INT i;
INT iLast = -1;
if ( !pVec ) {
pVec = VectorAlloc ( 5 );
fAppendVector ( &pVec, ZMMakeStr ( pstr ) );
return pVec;
}
for ( i = 0; i < pVec->count; i++ ) {
switch ( strcmp ( (PSTR) pVec->elem [ i ], pstr ) )
{
case -1:
/* pVec < pstr */
iLast = i;
break;
case 0:
/* equal */
return pVec;
case 1:
if ( fSorted )
goto gt;
}
}
gt:
pstr = ZMMakeStr ( pstr );
fAppendVector ( &pVec, pstr );
if ( fSorted && iLast < pVec->count - 2 ) {
for ( i = pVec->count - 2; i > iLast; i-- )
pVec->elem[ i + 1] = pVec->elem [ i ];
pVec->elem [ iLast + 1 ] = (VECTYPE)pstr;
}
return pVec;
}
/*
** UniqueStr - returns an allocated string that has
** redundant entries removed
**
** FREE's its input string !!
**
*/
PSTR PASCAL INTERNAL UniqueStr ( PSTR pstr, FLAG fSort )
{
PVECTOR pVec = NULL;
PSTR p = NULL;
PSTR q = NULL;
CHAR ch;
INT i;
if ( !pstr || !*( p = whiteskip ( pstr ) ) )
return ( ZMMakeStr ( strEMPTY ) );
while ( *p ) {
q = whitescan ( p );
ch = *q;
*q = '\0';
pVec = InsertVec ( pVec, p, fSort );
*q = ch;
p = whiteskip ( q );
}
if ( pVec ) {
p = ZMalloc ( strlen ( pstr ) + 2 );
*p = '\0';
for ( i = 0; i < pVec->count; i++ ) {
strcat ( p, ( PSTR ) pVec->elem [ i ] );
strcat ( p, strBLANK );
}
q = strend ( p );
*--q = '\0';
ZMVecFree ( pVec );
ZMfree ( pstr );
return ( p );
}
else
return ( ZMMakeStr ( strEMPTY ) );
}
/*
** SplitStr ( pstr, len)
** find last token in pstr in range [pstr .. pstr+len]
** if first token spans range, then first token after range
** if only one token in pstr, return end of pstr
*/
PSTR PASCAL INTERNAL SplitStr ( PSTR pstr, INT len )
{
PSTR p2 = pstr + len;
PSTR p1 = pstr;
PSTR q = NULL;
while ( ( q = NextToken ( p1 ) ) < p2 ) {
p1 = q;
if ( !*q )
break;
}
return ( p1 == pstr ? q : p1 );
}
FLAG PASCAL INTERNAL GetHdrInfo ( PHDRINFO pHdrInfo, PSTR pFileName, PSTR pMemory )
{
INT fEof;
INT i;
FILE *fp = NULL;
CHAR buf [ MAXLINELEN ];
PSTR pMem = NULL;
PSTR p = NULL;
LONG lTell = 0L;
PSTR rgszRemoveFromHeader [] = {
"Date:",
"Path:",
"Message-ID:",
"From:",
">From:",
"Reply-To:",
"Distribution:",
"Organization:",
"Lines:",
"Received:",
"Posted-Date:",
"X-",
"In-Reply-To:",
0 };
InitHdrInfo ( pHdrInfo );
/*
** use r+ so ftell can be trusted with files ending in ^Z
** fgetl will take care of \r\n nonsense
*/
if ( pFileName && ! (fp = fopen ( pFileName, "r+" ) ) )
return ERROR;
if ( pFileName ) {
fseek (fp, 0, SEEK_SET); /* BUGBUG - CRT bug - should not need */
fgetl ( buf, MAXLINELEN, fp );
}
else
pMem = mgetl ( buf, MAXLINELEN, pMemory );
for (;;) {
/*
** if buf is only white space (blank line) || <EOH> then we
** are done processing header
*/
if ( !*whiteskip ( buf ) || strpre (strEOH, buf ) )
break;
/*
** try to determine what field, if any, this line is
*/
for ( i = 0; rgstrFIELDS [ i ]; i++) {
if ( strpre ( rgstrFIELDS [ i ], buf ) ) {
p = buf + strlen ( rgstrFIELDS [ i ] );
/*
** we have first line of header field, is there anything
** on the line?
*/
for (;;) {
if (*(p = whiteskip(p) ) )
/*
** we have something on the line other than white space
** so save that something
*/
pHdrInfo->ppstr [ i ] = AppendSep (
pHdrInfo->ppstr [ i ], strBLANK, p, TRUE );
/*
** get next line, just in case we have a continuation
*/
if ( pFileName ) {
lTell = ftell ( fp );
if ( !fgetl ( buf, MAXLINELEN, fp ) )
goto eof;
}
else if ( !( pMem = mgetl ( buf, MAXLINELEN, pMem ) ) )
/*
** N.B. we test pMem NOT *pMem above
*/
goto eof;
/*
** if line is blank or strEOH or does not begin with
** linear whitespace then we do not have continuation
** so break and send buf back to the enclosing for loop
*/
if (!*buf || strpre ( strEOH, buf ) ||
(*buf != ' ' && *buf != '\t'))
break;
p = buf;
}
/*
** have processed a header and its continuation lines
** buf now contains the "next" line to be examined so
** break out of the for ( i = ... and get back to the for (;;)
*/
break;
}
}
/*
** if !rgstrFIELDS [ i ] then we didn't consume buf, it is an unknown
** field, so save it _with_only_LF's_ in pstrRestOfHdr
**
** The definitely unwanted fields possibly in the previous message
** are in rgszRemoveFromHeader.
*/
if ( !rgstrFIELDS [ i ] ) {
while (1) {
PSTR *pszTakeOut;
pszTakeOut = rgszRemoveFromHeader;
while (*pszTakeOut)
if (!strpre(*pszTakeOut, buf))
pszTakeOut++;
else
break;
for (;;) {
if (!(*pszTakeOut))
pHdrInfo->pstrRestOfHdr = AppendStr(pHdrInfo->pstrRestOfHdr,
buf, "\n", TRUE);
if ( pFileName ) {
lTell = ftell ( fp );
if ( !fgetl ( buf, MAXLINELEN, fp ) )
goto eof;
}
else if ( !( pMem = mgetl ( buf, MAXLINELEN, pMem ) ) )
goto eof;
if (!*buf || strpre ( strEOH, buf ) ||
(*buf != ' ' && *buf != '\t'))
break;
}
break;
}
}
}
/*
** buf contains a non-header line, it could be
** strEOH => current ftell is the beginning of body
** white space => blank line, next line is beginning of body
** no char => either eof in input or input was only a \n
** if eof then no body
** else ftell is beginning of body
*/
eof:
if ( pFileName ) {
if ( strpre ( strEOH, buf ) ) {
lTell = ftell ( fp );
/*
** fgetl returns NULL if eof
*/
fEof = !fgetl ( buf, MAXLINELEN, fp );
}
else
fEof = feof ( fp );
pHdrInfo->lBody = ( fEof ? -1L : lTell );
if ( pHdrInfo->lBody != -1 ) {
do {
if ( strpre ( strREPLYING, buf ) )
break;
lTell = ftell ( fp );
} while ( fgetl ( buf, MAXLINELEN, fp ) );
/*
** if feof then replying not found, so set lReplying to
** eof + 1 so that lReplying - lBody == # char in body
**
** lBody == -1 -> no body and -> lReplying == -1
*/
pHdrInfo->lReplying = lTell + ( feof ( fp ) ? 1 : 0 );
}
fclose ( fp );
}
else {
pHdrInfo->lBody = ( *pMem ? pMem - pMemory : -1 );
pHdrInfo->lReplying = -1;
}
return OK;
}
// GetCrntMsgHdr -- does a GetHdrInfo on the current active message
//
// Preconditions: InitHdrInfo (phdrInfo) has been called
//
// Postconditions: *phdrInfo will be left blank if there is no currently
// selected message or will be filled with the info
// for the first of:
// message in composition
// currently selected message
//
VOID PASCAL INTERNAL GetCrntMsgHdr( PHDRINFO phdrInfo )
{
PSTR pTmpFN2;
if ( hFocus == hCompose ) { //composing
SendMessage ( hCompose, CLOSEFILE, 0 );
GetHdrInfo ( phdrInfo, BackingFile ( hCompose ), NULL );
SendMessage ( hCompose, REOPNFILE, 1 );
}
else
if ( hFocus == hHeaders && inoteBold != -1 ) { //reading
pTmpFN2 = mktmpnam ( );
if ( IdocToFile ( mpInoteIdoc [ inoteBold ], pTmpFN2, 0 ) != ERROR ) {
GetHdrInfo ( phdrInfo, pTmpFN2, NULL );
_unlink ( pTmpFN2 );
}
ZMfree ( pTmpFN2 );
}
}
/*
** ExpandHdrInfoAliases ( pHdrInfo )
** for each string in To Cc Bcc Rrt
** check for private dl expansion
*/
VOID PASCAL INTERNAL ExpandHdrInfoAliases ( PHDRINFO pHdrInfo )
{
PSTR p = NULL;
PSTR q = NULL;
CHAR ch;
INT i, iHDR;
if ( !pVecDL && !(pVecDL = GetDistLists ( ) ) )
return;
for ( i = HDRTO; i <= HDRRRT; i++ ) {
if ( pHdrInfo->ppstr[i] ) {
pHdrInfo->ppstr[i] = ExpandAliases (pVecDL, (p = pHdrInfo->ppstr[i]),
TRUE );
ZMfree ( p );
p = whiteskip (pHdrInfo->ppstr[i]);
while ( *p ) {
q = NextToken ( p );
if ( *p == '$' ) {
ch = *q;
*q = '\0';
switch ( *(p+1) ) {
case 't':
iHDR = HDRTO;
break;
case 'c':
iHDR = HDRCC;
break;
case 'b':
iHDR = HDRBCC;
break;
case 'r':
iHDR = HDRRCD;
break;
default:
iHDR = -1;
break;
}
if ( iHDR == i ) {
*p++ = ' ';
*p = ' ';
p = q;
*q = ch;
} else if ( iHDR != -1 ) {
pHdrInfo->ppstr[ iHDR ] =
AppendSep ( pHdrInfo->ppstr[iHDR], strBLANK, p+2, TRUE );
*q = ch;
memmove ( p, q, strlen ( q ) + 1 );
} else
*q = ch;
}
else
p = q;
}
}
}
pHdrInfo->pstrRcd = UniqueStr ( pHdrInfo->pstrRcd, TRUE );
}
/*
** char *MakeSendFile ( pHdrInfo, pFileName )
** copies the To, Cc, Subject
** ignores the From, Bcc and Mail-Flags
** Make a new file and returns pointer to alloc'd string that is the name
*/
PSTR PASCAL INTERNAL MakeSendFile ( PHDRINFO pHdrInfo, PSTR pFileName )
{
time_t lNow;
struct timeb tstruct;
CHAR timewithzone[40];
PSTR pFileSend = NULL;
FILE *fpSend = NULL;
INT i;
pFileSend = mktmpnam ( );
fpSend = fopen ( pFileSend, "w+");
/*
** RRT must follow subject, don't send BCC RCD lines
*/
for ( i = HDRTO; i <= HDRSUBJ; i++ ) {
if ( i == HDRBCC || i == HDRRRT || i == HDRRCD )
continue;
PrintWithTest ( fpSend, rgstrFIELDS [ i ], pHdrInfo->ppstr [ i ],
( i == HDRTO || i == HDRSUBJ ), i != HDRSUBJ, fSortHdr );
}
PrintWithTest ( fpSend, rgstrFIELDS [ HDRRRT ], pHdrInfo->ppstr [ HDRRRT ],
FALSE, TRUE, fSortHdr );
//make Date: field
time ( &lNow );
ftime ( &tstruct );
//Following meets RFC 822 specs for datetime
strftime(timewithzone, 40, "%a, %d %b %y %X ", localtime( &lNow ));
strcat(timewithzone, tzname[daylight && tstruct.dstflag]);
fprintf ( fpSend, "Date: %s\n", timewithzone );
//append rest of header lines
fputs(pHdrInfo->pstrRestOfHdr, fpSend);
/* blank line */
fprintf ( fpSend, "\n" );
fclose ( fpSend );
AppendBody ( pFileSend, pFileName, pHdrInfo->lBody, pHdrInfo->lReplying );
return ( pFileSend );
}
/*
** char *MakeAbortFile ( pHdrInfo, pFileName, pSep )
** copies To Cc Bcc Rrt Rcd Subject
** ignores the From and Mail-Flags
** Make a new file and returns pointer to alloc'd string that is the name
*/
PSTR PASCAL INTERNAL MakeAbortFile (PHDRINFO pHdrInfo, PSTR pFileName, PSTR pSep)
{
PSTR pFileSend = NULL;
FILE *fpSend = NULL;
INT i;
pFileSend = mktmpnam ( );
fpSend = fopen ( pFileSend, "w+");
for ( i = HDRTO; i <= HDRSUBJ; i++ )
PrintWithTest ( fpSend, rgstrFIELDS [ i ], pHdrInfo->ppstr [ i ],
TRUE, i != HDRSUBJ, fSortHdr );
fputs(pHdrInfo->pstrRestOfHdr, fpSend);
fprintf ( fpSend, "%s\n", pSep );
fclose ( fpSend );
AppendBody ( pFileSend, pFileName, pHdrInfo->lBody, -1L );
return ( pFileSend );
}
FLAG PASCAL INTERNAL AppendBody ( PSTR pFileDest, PSTR pFileSrc, LONG lStart, LONG lStop )
{
FLAG fReturn = OK;
CHAR buf [ MAXLINELEN ];
INT fhDest, fhSrc;
INT cnt;
LONG l2Read;
if ( lStart < 0 || lStart == lStop )
return OK;
fhDest = open ( pFileDest, O_APPEND | O_RDWR | O_BINARY );
_lseek ( fhDest, 0L, SEEK_END );
fhSrc = open ( pFileSrc, O_RDONLY | O_BINARY );
if ( lStop == -1 ) {
_lseek ( fhSrc, 0L, SEEK_END );
lStop = tell ( fhSrc ) + 1;
}
_lseek ( fhSrc, lStart, SEEK_SET );
l2Read = lStop - lStart;
while ( l2Read ) {
cnt = ( ( l2Read > ( LONG ) MAXLINELEN ) ? ( INT ) MAXLINELEN :
(INT) ( l2Read ) ) ;
if ( ( cnt = read ( fhSrc, buf, cnt ) ) > 0 )
write ( fhDest, buf, cnt );
else {
fReturn = ERROR;
break;
}
l2Read -= (INT) cnt;
}
write ( fhDest, strCRLF, 2 );
close ( fhDest );
close ( fhSrc );
return fReturn;
}
VOID PASCAL INTERNAL PrintWithTest ( FILE *fp, PSTR pstr1, PSTR pstr2, FLAG fPrintNull, FLAG fUniqueSplit, FLAG fSort )
{
INT fNonNull = pstr2 && *pstr2;
PSTR pUnique = pstr2;
PSTR p1 = NULL;
PSTR p2 = NULL;
PSTR q = NULL;
CHAR ch;
if ( fPrintNull || fNonNull ) {
if ( fNonNull ) {
if ( fUniqueSplit )
pUnique = UniqueStr ( ZMMakeStr ( pUnique ), fSort );
p1 = pstr1;
p2 = pUnique;
while ( *p2 ) {
q = ( fUniqueSplit ? SplitStr ( p2, LINELENGTH - strlen ( p1 ) )
: strend ( p2 ) );
ch = *q;
*q = 0;
fprintf ( fp, "%s %s\n", p1, p2 );
*q = ch;
p2 = whiteskip ( q );
p1 = " ";
}
if ( fUniqueSplit )
ZMfree ( pUnique );
}
else
fprintf ( fp, "%s \n", pstr1 );
}
}
/*
** char *GetMailTo ( pHdrInfo )
** get a list of the To Cc Bcc
** strings in pHdrInfo may have duplicates, \n in string
** returned string does not have dupliates, no \n
*/
PSTR PASCAL INTERNAL GetMailTo ( PHDRINFO pHdrInfo )
{
PSTR p = NULL;
INT i;
for ( i = HDRTO; i <= HDRBCC; i++ )
p = AppendSep ( p, strBLANK, pHdrInfo->ppstr [ i], TRUE );
/*
** to remove duplicates
*/
return ( UniqueStr ( p, TRUE ) );
}
PSTR PASCAL INTERNAL VerifyHdrInfoAliases ( PHDRINFO pHdrInfo )
{
PSTR p = NULL;
PSTR q = NULL;
INT i;
for ( i = HDRTO; i <= HDRRRT; i++ ) {
if ( pHdrInfo->ppstr [ i ] &&
( q = AliasListOK(pHdrInfo->ppstr [i]) ) )
p = AppendSep(p, strBLANK, q, TRUE );
}
return p;
}
/*
** GetFrom - return string that is the from alias, if any
** else return NULL
**
** return value must be free'd
*/
PSTR PASCAL INTERNAL GetFrom ( PHDRINFO pHdrInfo )
{
PSTR p = NULL;
PSTR q = NULL;
if ( (p = pHdrInfo->pstrFrom ) ) {
p = ZMMakeStr ( pHdrInfo->pstrFrom );
/*
** remove the date part of the from line
*/
q = whitescan ( p );
*q = '\0';
}
return p;
}
/* MakeTempMail - create and fill the fields of a mail temp file
*
* arguements:
* pHdrInfo - contains To, Cc, Bcc, Rrt, Rcd, Subject
*
* return value:
* NULL an error occured.
* valid ptr pointer to name of file created, it is closed
* pointed to string needs to be free'd
*/
PSTR PASCAL INTERNAL MakeTempMail ( PHDRINFO pHdrInfo )
{
FILE *fp = NULL;
PSTR pTmpFN = NULL;
INT i;
pTmpFN = mktmpnam ( );
if ( pTmpFN ) {
if ( ( fp = fopen ( pTmpFN, "w" ) ) ) {
for ( i = HDRTO; i <= HDRSUBJ; i++ )
PrintWithTest ( fp, rgstrFIELDS [ i ], pHdrInfo->ppstr [ i ],
TRUE, i != HDRSUBJ, fSortHdr );
if (*pHdrInfo->pstrRestOfHdr)
fputs(pHdrInfo->pstrRestOfHdr, fp);
fprintf ( fp, "%s\n", strEOH );
fclose ( fp );
return pTmpFN;
}
ZMfree ( pTmpFN );
}
SendMessage ( hCommand, DISPLAY, "Unable to create message temp file." );
SendMessage ( hCommand, DISPLAY, "(Check TMP environment variable and disk space.)");
return NULL;
}
/*
** RmvToken - remove pToken from string pString by shifting left
** pToken need not be part of string
**
*/
VOID PASCAL INTERNAL RmvToken ( PSTR pString, PSTR pToken )
{
PSTR p = NULL;
PSTR q = NULL;
PSTR pchEndToken = NULL;
CHAR chLastChar = '\0';
CHAR ch;
if ( !( p = pString ) )
return;
pchEndToken = whitescan ( pToken );
chLastChar = *pchEndToken;
*pchEndToken = '\0';
while ( *p ) {
q = whitescan ( p );
ch = *q;
*q = '\0';
if ( strcmpis ( p, pToken ) ) {
/* NOT equal */
*q = ch;
p = NextToken ( p );
}
else {
/* equal */
*q = ch;
q = NextToken ( p );
memmove ( p, q, strlen ( q ) + 1 );
}
}
*pchEndToken = chLastChar;
}
VOID PASCAL INTERNAL NotifyTools (void)
{
FLAG fUpdIni = FALSE;
FLAG fHEAPDUMP = fNotifyTools & F_SENDHEAPDUMP;
PSTR pTmpFN = NULL;
PSTR pTmpHD = NULL;
PSTR pTmp = NULL;
/*
** if ( fNotifyTools & F_NEWVERSION )
** new version of wzmail, so notify tools
** if ( fNotifyTools & F_SENDHEAPDUMP )
** we crashed with last time WZMAIL was run due to out of heap
** space and the file strHEAPDUMP was created. So now send the
** file to tools and delete it.
*/
if ( fComposeOnBoot || !fCurFldIsDefFld ||
( !(fNotifyTools & (F_NEWVERSION | F_SENDHEAPDUMP ) ) ) )
return;
fNotifyTools &= ~(FLAG)F_NEWVERSION;
fNotifyTools &= ~(FLAG)F_SENDHEAPDUMP;
if ( fUpdIni )
SpecificHlp ( "News" );
}
/*
** SendIdoc - send the message idoc in the current folder
** returns nonzero if error else zero
*/
INT PASCAL INTERNAL SendIdoc ( IDOC idoc )
{
HDRINFO hdrInfo;
PSTR pTmpFN = NULL;
INT rtn = 1;
WndPrintf (hCommand, "Sending %d\r\n", IDOCTODOC (idoc));
pTmpFN = mktmpnam ( );
if ( IdocToFile ( idoc, pTmpFN, 1 ) == ERROR )
{
SendMessage ( hCommand, DISPLAY, "Unable to open temp file." );
SendMessage ( hCommand, DISPLAY, "(Check TMP environment variable and disk space.)");
}
else {
InitHdrInfo ( &hdrInfo );
GetHdrInfo ( &hdrInfo, pTmpFN, NULL );
if ( hdrInfo.pstrFrom )
SendMessage ( hCommand, DISPLAY, "\"From\" not null." );
else if ( !MailFile ( pTmpFN, TRUE ) ) {
ChangeHeaderFlag ( idoc, F_DELETED, FALSE );
rtn = 0;
_unlink ( pTmpFN );
}
FreeHdrInfo ( &hdrInfo, HDRALL );
}
ZMfree ( pTmpFN );
return rtn;
}