Files
cdesktop/cde/programs/dtcm/dtcm/submit.c
2018-07-04 23:09:18 +01:00

438 lines
9.8 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
**
** submit.c
**
** $XConsortium: submit.c /main/5 1996/10/03 10:58:04 drk $
**
** RESTRICTED CONFIDENTIAL INFORMATION:
**
** The information in this document is subject to special
** restrictions in a confidential disclosure agreement between
** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
** document outside HP, IBM, Sun, USL, SCO, or Univel without
** Sun's specific written approval. This document and all copies
** and derivative works thereof must be returned or destroyed at
** Sun's request.
**
** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
**
*******************************************************************************/
/* *
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#ifndef lint
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <LocaleXlate.h>
#include <RFCMIME.h>
#include "rerule.h" /* FALSE */
static char **
arpaPhrase(const char * name)
{
char c;
const char *cp;
char * cp2;
int gotlt, lastsp, didq;
int nesting;
const char * last_comma = name;
int biggest = 0;
int n_addrs = 0;
int cur_addr;
int distance;
char ** addrs;
const char * comma;
const char * start;
if (name == (char *) 0) {
return(NULL);
}
/* We need to figure out what is the biggest possible address.
This will be the maximum distance between commas.
*/
for (comma = name; *comma; comma++) {
if (*comma == ',') {
n_addrs += 1;
distance = comma - last_comma;
biggest = biggest < distance ? distance : biggest;
last_comma = comma;
}
}
distance = comma - last_comma;
biggest = biggest < distance ? distance : biggest;
biggest += 2; /* Just in case. */
cur_addr = 0;
addrs = (char **)malloc((n_addrs + 1) * sizeof(char *));
cp2 = (char *)malloc(biggest);
addrs[cur_addr++] = cp2;
gotlt = 0;
lastsp = 0;
start = name;
for (cp = name; (c = *cp++) != 0;) {
switch (c) {
case '(':
/*
Start of a comment, ignore it.
*/
nesting = 1;
while ((c = *cp) != 0) {
cp++;
switch(c) {
case '\\':
if (*cp == 0) goto outcm;
cp++;
break;
case '(':
nesting++;
break;
case ')':
--nesting;
break;
}
if (nesting <= 0) break;
}
outcm:
lastsp = 0;
break;
case '"':
/*
Start a quoted string.
Copy it in its entirety.
*/
didq = 0;
while ((c = *cp) != 0) {
cp++;
switch (c) {
case '\\':
if ((c = *cp) == 0) goto outqs;
cp++;
break;
case '"':
goto outqs;
}
if (gotlt == 0 || gotlt == '<') {
if (lastsp) {
lastsp = 0;
*cp2++ = ' ';
}
if (!didq) {
*cp2++ = '"';
didq++;
}
*cp2++ = c;
}
}
outqs:
if (didq)
*cp2++ = '"';
lastsp = 0;
break;
case ' ':
case '\t':
case '\n':
done:
*cp2 = 0;
cp2 = (char *)malloc(biggest);
addrs[cur_addr++] = cp2;
lastsp = 1;
break;
case ',':
*cp2++ = c;
if (gotlt != '<') {
gotlt = 0;
goto done;
}
break;
case '<':
cp2 = addrs[cur_addr - 1];
gotlt = c;
lastsp = 0;
break;
case '>':
if (gotlt == '<') {
gotlt = c;
break;
}
/* FALLTHROUGH . . . */
default:
if (gotlt == 0 || gotlt == '<') {
if (lastsp) {
lastsp = 0;
*cp2++ = ' ';
}
*cp2++ = c;
}
break;
}
}
*cp2 = 0;
addrs[cur_addr] = NULL;
return(addrs);
}
static char *
formatMessage(char ** addrs, const char * subject, const char * body)
{
char * msg;
int size = 0;
int line;
char ** to;
int isAllASCII;
char hdr_buf[1024];
_DtXlateDb db = NULL;
char plat[_DtPLATFORM_MAX_LEN];
int execver;
int compver;
int body_len;
char digest[16];
char mime_type[64];
char tmpbuf[20];
char *ret_locale = NULL;
char *ret_lang = NULL;
char *ret_codeset = NULL;
char default_charset[64];
char *NewBuf = NULL;
unsigned long _len = 0;
Encoding enc;
/* Figure out how big we need the buffer to be. */
for (to = addrs; *to; to++) {
size += strlen(*to);
size += 2; /* Leave room for the , */
}
size += strlen(subject);
size += strlen(body);
/* We will need space for the header names, a blank line, and
other general formatting things. We could be exact, but
1024 is more than enough and give us some spare.
*/
size += 1024;
msg = (char *)malloc(size);
strcpy(msg, "To: ");
line = 4;
for (to = addrs; *to; to++) {
strcat(msg, *to);
if (*(to + 1) != NULL) {
strcat(msg, ", ");
line += strlen(*to);
if (line > 72) {
strcat(msg, "\n ");
line = 0;
}
}
}
strcat(msg, "\nSubject: ");
/* Encode the body of the message */
/* 1) Open Lcx data bases */
if ((_DtLcxOpenAllDbs(&db) == 0) &&
(_DtXlateGetXlateEnv(db,plat,&execver,&compver) != 0))
{
_DtLcxCloseDb(&db);
strcat(msg, subject);
if (msg[strlen(msg) - 1] == '\n') {
msg[strlen(msg) - 1] = 0;
}
strcat(msg, "\nMime-Version: 1.0\n");
strcat(msg, "Content-Type: text/plain;charset=us-ascii\n\n");
strcat(msg, body);
}
else
{
body_len = strlen(body);
hdr_buf[0]='\0';
strcpy(mime_type,"text/plain");
rfc1522cpy(hdr_buf,subject);
strcat(hdr_buf,"Mime-Version: 1.0\n");
isAllASCII= CvtStr((char *)NULL,(void *)body,(unsigned long)body_len,(void**)&NewBuf, &_len, CURRENT_TO_INTERNET);
enc = getEncodingType(body,body_len,FALSE);
/*
* Here is an ugly adjustment again. If mime_type is text/plain and if
* ret_codeset is ISO-2022-JP/KR/TW/CN, we have to always use
* enc = MIME_7BIT
* This means if the user inputs UDC/VDC into the e-mail body,
* fold7 may convert it to the string with MSB-on character and
* dtmail passes it to sendmail as if I had all 7bit chars.
*/
getCharSet(default_charset);
DtXlateOpToStdLocale(DtLCX_OPER_MIME, default_charset,
&ret_locale, &ret_lang, &ret_codeset);
if ( !strncasecmp( mime_type, "text/plain", 10 ) &&
( !strncasecmp( ret_codeset, "ISO-2022-JP", 11 ) ||
!strncasecmp( ret_codeset, "ISO-2022-KR", 11 ) ||
!strncasecmp( ret_codeset, "ISO-2022-TW", 11 ) ||
!strncasecmp( ret_codeset, "ISO-2022-CN", 11 ) ) )
enc = MIME_7BIT;
memset(digest,0,sizeof(digest));
md5PlainText(body,body_len,digest);
writeContentHeaders(hdr_buf,mime_type,enc,(char *)digest,isAllASCII);
strcat(hdr_buf,"\n");
strcat(hdr_buf,"Content-Length: ");
if (( NewBuf != NULL) && ( _len != 0))
{
sprintf(tmpbuf,"%ld",_len);
strcat(hdr_buf,tmpbuf);
strcat(hdr_buf,"\n");
strcat(msg,hdr_buf);
strncat(msg,NewBuf,_len);
strcat(hdr_buf,"\n");
}
else
{
sprintf(tmpbuf,"%d",body_len);
strcat(hdr_buf,tmpbuf);
strcat(hdr_buf,"\n");
strcat(msg,hdr_buf);
strcat(msg,body);
}
}
free(ret_codeset);
free(ret_lang);
free(ret_locale);
return(msg);
}
static int
deliver(char ** addrs, char * msg)
{
char ** argv;
int fd[2];
int c_pid;
int status;
int n_addrs;
int cp;
for (n_addrs = 0; addrs[n_addrs]; n_addrs++) {
continue;
}
argv = (char **)malloc((n_addrs + 2) * sizeof(char *));
argv[0] = "/usr/lib/sendmail";
for (cp = 0; addrs[cp]; cp++) {
argv[cp + 1] = addrs[cp];
}
argv[cp + 1] = NULL;
if(-1 == pipe(fd)) {
fprintf(stderr, "pipe() failed %d '%s'\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
c_pid = fork();
if (c_pid < 0) {
return(c_pid);
}
if (c_pid == 0) { /* The child. */
dup2(fd[0], STDIN_FILENO);
execvp("/usr/lib/sendmail", (char *const *)argv);
_exit(1); /* This had better never happen! */
}
else { /* The parent. */
if(-1 == write(fd[1], msg, strlen(msg))) {
fprintf(stderr, "write() failed %d '%s'\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
close(fd[0]);
close(fd[1]);
waitpid(c_pid, &status, 0);
}
return(status);
}
int
submit_mail(const char * to,
const char * subject,
const char * body)
{
char ** addrs;
char ** ad;
char * msg;
int status;
/*
Parse the address list so we can form a reasonable one
for the user to see in the message.
*/
addrs = arpaPhrase(to);
msg = formatMessage(addrs, subject, body);
status = deliver(addrs, msg);
for (ad = addrs; *ad; ad++) {
free(*ad);
}
free(addrs);
free(msg);
return(status);
}