|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 19017 (0x4a49)
Types: TextFile
Names: »mailmsg2.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/mailmsg2.c«
/** mailmsg2.c **/
/** Interface to allow mail to be sent to users. Part of ELM **/
/** (C) Copyright 1986, Dave Taylor **/
#include "headers.h"
#include <errno.h>
extern int errno;
char *error_name(), *error_description(), *strip_parens();
char *strcat(), *strcpy();
char *format_long(), *strip_commas(), *tail_of_string();
unsigned long sleep();
#ifdef SITE_HIDING
char *get_ctime_date();
#endif
FILE *write_header_info();
extern char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN],
priority [SLEN], to[VERY_LONG_STRING], cc[VERY_LONG_STRING],
in_reply_to[SLEN], expanded_to[VERY_LONG_STRING],
expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN];
#ifdef ALLOW_BCC
extern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
#endif
int gotten_key = 0;
char *bounce_off_remote();
mail(copy_msg, edit_message, batch, form)
int copy_msg, edit_message, batch, form;
{
/** Given the addresses and various other miscellany (specifically,
'copy-msg' indicates whether a copy of the current message should
be included, 'edit_message' indicates whether the message should
be edited and 'batch' indicates that the message should be read
from stdin) this routine will invoke an editor for the user and
then actually mail off the message. 'form' can be YES, NO, or
MAYBE. YES=add "Content-Type: mailform" header, MAYBE=add the
M)ake form option to last question, and NO=don't worry about it!
Also, if 'copy_msg' = FORM, then grab the form temp file and use
that...
**/
FILE *reply, *real_reply; /* second is post-input buffer */
char filename[SLEN], filename2[SLEN], fname[SLEN],
very_long_buffer[VERY_LONG_STRING];
char ch;
register int retransmit = FALSE;
int already_has_text = FALSE; /* we need an ADDRESS */
static int cancelled_msg = 0;
dprint2(4,"\nMailing to '%s'(with%s editing)\n",
expanded_to, edit_message? "" : "out");
/** first generate the temporary filename **/
sprintf(filename,"%s%d",temp_file, getpid());
/** if possible, let's try to recall the last message? **/
if (! batch && copy_msg != FORM && user_level != 0)
retransmit = recall_last_msg(filename, copy_msg, &cancelled_msg,
&already_has_text);
/** if we're not retransmitting, create the file.. **/
if (! retransmit)
if ((reply = fopen(filename,"w")) == NULL) {
dprint2(1,
"Attempt to write to temp file %s failed with error %s (mail)\n",
filename, error_name(errno));
error2("Could not create file %s (%s)",filename,
error_name(errno));
return(1);
}
if (batch) {
Raw(OFF);
if (isatty(fileno(stdin))) {
fclose(reply); /* let edit-the-message open it! */
printf("To: %s\nSubject: %s\n", expanded_to, subject);
strcpy(editor, "none"); /* force inline editor */
if (no_editor_edit_the_message(filename)) {
return(0); /* confused? edit_the_msg returns 1 if bad */
}
if (verify_transmission(filename, &form) == 'f')
return(0);
}
else {
while (gets(very_long_buffer) != NULL)
fprintf(reply, "%s\n", very_long_buffer);
}
}
if (copy_msg == FORM) {
sprintf(fname, "%s%d", temp_form_file, getpid());
fclose(reply); /* we can't retransmit a form! */
if (access(fname,ACCESS_EXISTS) != 0) {
error("couldn't find forms file!");
return(0);
}
unlink(filename);
dprint2(4, "-- linking existing file %s to file %s --\n",
fname, filename);
link(fname, filename);
unlink(fname);
}
else if (copy_msg && ! retransmit) /* if retransmit we have it! */
if (edit_message) {
copy_message(prefixchars, reply, noheader, FALSE);
already_has_text = TRUE; /* we just added it, right? */
}
else
copy_message("", reply, noheader, FALSE);
if (!batch && ! retransmit && signature && copy_msg != FORM) {
fprintf(reply, "\n--\n"); /* News 2.11 compatibility? */
if (chloc(expanded_to, '!') == -1 && chloc(expanded_to, '@') == -1) {
if (strlen(local_signature) > 0) {
if (local_signature[0] != '/')
sprintf(filename2, "%s/%s", home, local_signature);
else
strcpy(filename2, local_signature);
(void) append(reply, filename2);
already_has_text = TRUE; /* added signature... */
}
}
else {
if (remote_signature[0] != '/')
sprintf(filename2, "%s/%s", home, remote_signature);
else
strcpy(filename2, remote_signature);
(void) append(reply, filename2);
already_has_text = TRUE; /* added signature... */
}
}
if (! retransmit && copy_msg != FORM)
(void) fclose(reply); /* on replies, it won't be open! */
/** Edit the message **/
if (edit_message)
create_readmsg_file(); /* for "readmsg" routine */
ch = edit_message? 'e' : ' '; /* drop through if needed... */
if (! batch) {
do {
switch (ch) {
case 'e': if (edit_the_message(filename, already_has_text)) {
cancelled_msg = TRUE;
return(1);
}
break;
case 'h': edit_headers(); break;
default : /* do nothing */ ;
}
/** ask that silly question again... **/
if ((ch = verify_transmission(filename, &form)) == 'f') {
cancelled_msg = TRUE;
return(1);
}
} while (ch != 's');
if (form == YES)
if (format_form(filename) < 1) {
cancelled_msg = TRUE;
return(1);
}
if ((reply = fopen(filename,"r")) == NULL) {
dprint2(1,
"Attempt to open file %s for reading failed with error %s (mail)\n",
filename, error_name(errno));
error1("Could not open reply file (%s)", error_name(errno));
return(1);
}
}
else if ((reply = fopen(filename,"r")) == NULL) {
dprint2(1,
"Attempt to open file %s for reading failed with error %s (mail)\n",
filename, error_name(errno));
error1("Could not open reply file (%s)", error_name(errno));
return(1);
}
cancelled_msg = FALSE; /* it ain't cancelled, is it? */
/** ask about bounceback if the user wants us to.... **/
if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM)
if (verify_bounceback() == TRUE) {
if (strlen(cc) > 0) strcat(expanded_cc, ", ");
strcat(expanded_cc, bounce_off_remote(to));
}
/** grab a copy if the user so desires... **/
if (auto_cc && !batch)
save_copy(subject, expanded_to, expanded_cc, filename, to);
/** write all header information into real_reply **/
sprintf(filename2,"%s%d",temp_file, getpid()+1);
/** try to write headers to new temp file **/
dprint2(6, "Composition file='%s' and mail buffer='%s'\n",
filename, filename2);
if ((real_reply=write_header_info(filename2, expanded_to, expanded_cc,
#ifdef ALLOW_BCC
expanded_bcc,
#endif
form == YES)) == NULL) {
/** IT FAILED!! MEIN GOTT! Use a dumb mailer instead! **/
dprint1(3,"** write_header failed: %s\n", error_name(errno));
if (cc[0] != '\0') /* copies! */
sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
mailx, subject, strip_parens(strip_commas(expanded_to)),
remove, filename, filename);
error1("Message sent using dumb mailer - %s", mailx);
sleep(2); /* ensure time to see this prompt! */
}
else {
copy_message_across(reply, real_reply);
fclose(real_reply);
if (cc[0] != '\0') /* copies! */
sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
#ifdef ALLOW_BCC
if (bcc[0] != '\0') {
strcat(expanded_to, " ");
strcat(expanded_to, expanded_bcc);
}
#endif
if (access(sendmail, EXECUTE_ACCESS) == 0
#ifdef SITE_HIDING
&& ! is_a_hidden_user(username))
#else
)
#endif
sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s",
sendmail, smflags, strip_parens(strip_commas(expanded_to)),
remove, filename2, filename2);
else /* oh well, use default mailer... */
sprintf(very_long_buffer,"( (%s %s ; %s %s) & ) < %s",
mailer, strip_parens(strip_commas(expanded_to)),
remove, filename2, filename2);
}
fclose(reply);
if (mail_only) {
printf("sending mail...");
fflush(stdout);
}
else {
PutLine0(LINES,0,"sending mail...");
CleartoEOLN();
}
system_call(very_long_buffer, SH);
if (mail_only)
printf("\rmail sent! \n\r");
else
set_error("Mail sent!");
return(TRUE);
}
mail_form(address, subj)
char *address, *subj;
{
/** copy the appropriate variables to the shared space... */
strcpy(subject, subj);
strcpy(to, address);
strcpy(expanded_to, address);
return(mail(FORM, NO, NO, NO));
}
int
recall_last_msg(filename, copy_msg, cancelled_msg, already_has_text)
char *filename;
int copy_msg, *cancelled_msg, *already_has_text;
{
/** If filename exists and we've recently cancelled a message,
the ask if the user wants to use that message instead! This
routine returns TRUE if the user wants to retransmit the last
message, FALSE otherwise...
**/
register int retransmit = FALSE;
if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
Raw(ON);
CleartoEOLN();
if (copy_msg)
PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
BACKSPACE);
else
PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c",
BACKSPACE);
fflush(stdout);
if (tolower(ReadCh()) != 'n') {
Write_to_screen("Yes",0);
retransmit++;
*already_has_text = TRUE;
}
else
Write_to_screen("No",0);
fflush(stdout);
*cancelled_msg = 0;
}
return(retransmit);
}
int
verify_transmission(filename, form_letter)
char *filename;
int *form_letter;
{
/** Ensure the user wants to send this. This routine returns
the character entered. Modified compliments of Steve Wolf
to add the'dead.letter' feature.
Also added form letter support...
**/
FILE *deadfd, *messagefd;
char ch, buffer[LONG_SLEN], fname[SLEN];
if (mail_only) {
if (isatty(fileno(stdin))) {
printf("\n\rAre you sure you want to send this? (y/n) ");
CleartoEOLN();
printf("y%c", BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
if (tolower(ReadCh()) == 'n') { /* >SIGH< */
printf("No\n\r\n\r");
/** try to save it as a dead letter file **/
sprintf(fname, "%s/%s", home, dead_letter);
if ((deadfd = fopen(fname,"a")) == NULL) {
dprint2(1,
"\nAttempt to append to deadletter file '%s' failed: %s\n\r",
fname, error_name(errno));
printf("Message not saved, Sorry.\n\r\n\r");
return('f');
}
else if ((messagefd = fopen(filename, "r")) == NULL) {
dprint2(1,"\nAttempt to read reply file '%s' failed: %s\n\r",
filename, error_name(errno));
printf("Message not saved, Sorry.\n\r\n\r");
return('f');
}
/* if we get here we're okay for everything, right? */
while (fgets(buffer, LONG_SLEN, messagefd) != NULL)
fputs(buffer, deadfd);
fclose(messagefd);
fclose(deadfd);
printf("Message saved in file \"$HOME/%s\"\n\r\n\r", dead_letter);
return('f'); /* forget it! */
}
else
printf("Yes\n\r\n\r");
return('s'); /* send this baby! */
}
else
return('s'); /* ditto */
}
else if (check_first) { /* used to check strlen(infile) > 0 too? */
reprompt:
MoveCursor(LINES,0);
CleartoEOLN();
ClearLine(LINES-1);
if (user_level == 0)
PutLine1(LINES-1,0, "Are you sure you want to send this? (y/n) y%c",
BACKSPACE);
else if (*form_letter == PREFORMATTED)
PutLine1(LINES-1, 0,
"Choose: edit H)eaders, S)end, or F)orget : s%c",
BACKSPACE);
else if (*form_letter == YES)
PutLine1(LINES-1, 0,
"Choose: E)dit form, edit H)eaders, S)end, or F)orget : s%c",
BACKSPACE);
else if (*form_letter == MAYBE)
PutLine1(LINES-1, 0,
"Choose: E)dit msg, edit H)eaders, M)ake form, S)end, or F)orget : s%c",
BACKSPACE);
else
PutLine1(LINES-1, 0,
"Please choose: E)dit msg, edit H)eaders, S)end, or F)orget : s%c",
BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
Raw(ON); /* double check... testing only... */
ch = tolower(ReadCh());
if (user_level == 0) {
if (ch == 'n') {
set_error("message cancelled");
return('f');
}
else
return('s');
}
/* otherwise someone who knows what's happenin' so... */
switch (ch) {
case 'f': Write_to_screen("Forget",0);
set_error(
"Message kept - Can be restored at next F)orward, M)ail or R)eply ");
break;
case '\n' :
case '\r' :
case 's' : Write_to_screen("Send",0);
ch = 's'; /* make sure! */
break;
case 'm' : if (*form_letter == MAYBE) {
*form_letter = YES;
switch (check_form_file(filename)) {
case -1 : return('f');
case 0 : *form_letter = MAYBE; /* check later!*/
error("No fields in form!");
return('e');
default : goto reprompt;
}
}
else {
Write_to_screen("%c??", 1, 07); /* BEEP */
sleep(1);
goto reprompt; /* yech */
}
case 'e' : if (*form_letter != PREFORMATTED) {
Write_to_screen("Edit",0);
if (*form_letter == YES)
*form_letter = MAYBE;
}
else {
Write_to_screen("%c??", 1, 07); /* BEEP */
sleep(1);
goto reprompt; /* yech */
}
break;
case 'h' : Write_to_screen("Headers",0);
break;
default : Write_to_screen("%c??", 1, 07); /* BEEP */
sleep(1);
goto reprompt; /* yech */
}
return(ch);
}
else return('s');
}
FILE *
#ifdef ALLOW_BCC
write_header_info(filename, long_to, long_cc, long_bcc, form)
char *filename, *long_to, *long_cc, *long_bcc;
#else
write_header_info(filename, long_to, long_cc, form)
char *filename, *long_to, *long_cc;
#endif
int form;
{
/** Try to open filedesc as the specified filename. If we can,
then write all the headers into the file. The routine returns
'filedesc' if it succeeded, NULL otherwise. Added the ability
to have backquoted stuff in the users .elmheaders file!
**/
static FILE *filedesc; /* our friendly file descriptor */
#ifdef SITE_HIDING
char buffer[SLEN];
int is_hidden_user; /* someone we should know about? */
#endif
char *get_arpa_date();
if ((filedesc = fopen(filename, "w")) == NULL) {
dprint1(1,
"Attempt to open file %s for writing failed! (write_header_info)\n",
filename);
dprint2(1,"** %s - %s **\n\n", error_name(errno),
error_description(errno));
error2("Error %s encountered trying to write to %s",
error_name(errno), filename);
sleep(2);
return(NULL); /* couldn't open it!! */
}
#ifdef SITE_HIDING
if ((is_hidden_user = is_a_hidden_user(username))) {
/** this is the interesting part of this trick... **/
sprintf(buffer, "From %s!%s %s\n", HIDDEN_SITE_NAME,
username, get_ctime_date());
fprintf(filedesc, "%s", buffer);
dprint1(1,"\nadded: %s", buffer);
/** so is this perverted or what? **/
}
#endif
fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
fprintf(filedesc,"Date: %s\n", get_arpa_date());
#ifndef DONT_ADD_FROM
# ifdef SITE_HIDING
if (is_hidden_user)
fprintf(filedesc,"From: %s <%s!%s!%s>\n", full_username,
hostname, HIDDEN_SITE_NAME, username);
else
# endif
# ifdef INTERNET_ADDRESS_FORMAT
# ifdef USE_DOMAIN
fprintf(filedesc,"From: %s <%s@%s%s>\n", full_username,
username, hostname, DOMAIN);
# else
fprintf(filedesc,"From: %s <%s@%s>\n", full_username,
username, hostname);
# endif
# else
fprintf(filedesc,"From: %s <%s!%s>\n", full_username,
hostname, username);
# endif
#endif
fprintf(filedesc, "Subject: %s\n", subject);
if (cc[0] != '\0')
fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
#ifdef ALLOW_BCC
if (bcc[0] != '\0')
fprintf(filedesc, "Bcc: %s\n", format_long(long_bcc, strlen("Bcc: ")));
#endif
if (strlen(action) > 0)
fprintf(filedesc, "Action: %s\n", action);
if (strlen(priority) > 0)
fprintf(filedesc, "Priority: %s\n", priority);
if (strlen(expires) > 0)
fprintf(filedesc, "Expiration-Date: %s\n", expires);
if (strlen(reply_to) > 0)
fprintf(filedesc, "Reply-To: %s\n", reply_to);
if (strlen(in_reply_to) > 0)
fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
if (strlen(user_defined_header) > 0)
fprintf(filedesc, "%s\n", user_defined_header);
add_mailheaders(filedesc);
if (form)
fprintf(filedesc, "Content-Type: mailform\n");
fprintf(filedesc, "X-Mailer: Elm [version %s]\n\n", VERSION);
return((FILE *) filedesc);
}
copy_message_across(source, dest)
FILE *source, *dest;
{
/** copy the message in the file pointed to by source to the
file pointed to by dest. **/
int crypted = FALSE; /* are we encrypting? */
int encoded_lines = 0; /* # lines encoded */
char buffer[LONG_SLEN]; /* file reading buffer */
while (fgets(buffer, LONG_SLEN, source) != NULL) {
if (buffer[0] == '[') {
if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
crypted = TRUE;
else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
crypted = FALSE;
else if (strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
continue; /* next line? */
}
else if (crypted) {
if (! gotten_key++)
getkey(ON);
else if (! encoded_lines++)
get_key_no_prompt(); /* reinitialize.. */
encode(buffer);
}
fputs(buffer, dest);
}
}
int
verify_bounceback()
{
/** Ensure the user wants to have a bounceback copy too. (This is
only called on messages that are greater than the specified
threshold hops and NEVER for non-uucp addresses.... Returns
TRUE iff the user wants to bounce a copy back....
**/
if (mail_only) {
printf("Would you like a copy \"bounced\" off the remote? (y/n) ");
CleartoEOLN();
printf("n%c", BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
if (tolower(ReadCh()) != 'y') {
printf("No\n\r");
return(FALSE);
}
else
printf("Yes - Bounceback included\n\r");
}
else {
MoveCursor(LINES,0);
CleartoEOLN();
PutLine1(LINES,0,
"\"Bounce\" a copy off the remote machine? (y/n) y%c",
BACKSPACE);
fflush(stdin); /* wait for answer! */
fflush(stdout);
if (tolower(ReadCh()) != 'y') {
Write_to_screen("No", 0);
fflush(stdout);
return(FALSE);
}
Write_to_screen("Yes!", 0);
fflush(stdout);
}
return(TRUE);
}