|
|
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 e
Length: 12220 (0x2fbc)
Types: TextFile
Names: »editmsg.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/editmsg.c«
/** editmsg.c **/
/** This contains routines to do with starting up and using an editor (or two)
from within Elm. This stuff used to be in mailmsg2.c...
(C) Copyright 1986, Dave Taylor
**/
#include "headers.h"
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
extern int errno;
char *error_name(), *error_description(), *strcpy();
unsigned long sleep();
int
edit_the_message(filename, already_has_text)
char *filename;
int already_has_text;
{
/** Invoke the users editor on the filename. Return when done.
If 'already has text' then we can't use the no-editor option
and must use 'alternative editor' (e.g. $EDITOR or default_editor)
instead... **/
char buffer[SLEN];
register int stat, return_value = 0;
buffer[0] = '\0';
if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
if (already_has_text)
sprintf(buffer, "%s %s", alternative_editor, filename);
else
return(no_editor_edit_the_message(filename));
}
PutLine0(LINES, 0, "invoking editor..."); fflush(stdout);
if (strlen(buffer) == 0)
sprintf(buffer,"%s %s", editor, filename);
Raw(OFF);
chown(filename, userid, groupid); /* file was owned by root! */
if (cursor_control)
transmit_functions(OFF); /* function keys are local */
if ((stat = system_call(buffer, SH)) != 0) {
dprint1(1,"System call failed with stat %d (edit_the_message)\n",
stat);
error1("Can't invoke editor '%s' for composition", editor);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
ClearLine(LINES-1);
sleep(2);
return_value = 1;
}
if (cursor_control)
transmit_functions(ON); /* function keys are local */
Raw(ON);
return(return_value);
}
extern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING],
expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING],
subject[SLEN];
int interrupts_while_editing; /* keep track 'o dis stuff */
jmp_buf edit_location; /* for getting back from interrupt */
#ifdef ALLOW_BCC
extern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
#endif
char *strip_commas();
int
no_editor_edit_the_message(filename)
char *filename;
{
/** If the current editor is set to either "builtin" or "none", then
invoke this program instead. As it turns out, this and the
routine above have a pretty incestuous relationship (!)...
**/
FILE *edit_fd;
char buffer[SLEN], editor_name[SLEN];
int edit_interrupt(), (*oldint)(), (*oldquit)();
Raw(OFF);
if ((edit_fd = fopen(filename, "a")) == NULL) {
error2("Couldn't open %s for appending [%s]", filename,
error_name(errno));
sleep (2);
dprint1(1,"Error encountered trying to open file %s;\n", filename);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
Raw(ON);
return(1);
}
/** file open...let's start accepting input! **/
printf(
"\nPlease enter message, ^D to end, or ~? <RETURN> for help;\n\n");
oldint = signal(SIGINT, edit_interrupt);
oldquit = signal(SIGQUIT, edit_interrupt);
interrupts_while_editing = 0;
more_input:
while (gets(buffer) != NULL) {
if (setjmp(edit_location) != 0) {
if (interrupts_while_editing > 1) {
Raw(ON);
(void) signal(SIGINT, oldint);
(void) signal(SIGQUIT, oldquit);
if (edit_fd != NULL) /* insurance... */
fclose(edit_fd);
return(1);
}
goto more_input; /* read input again, please! */
}
interrupts_while_editing = 0; /* reset to zero... */
if (strcmp(buffer, ".") == 0)
break; /* '.' is as good as a ^D to us dumb programs :-) */
if (buffer[0] == TILDE)
switch (tolower(buffer[1])) {
case '?' : tilde_help(); printf("(continue)\n"); goto more_input;
case '~' : move_left(buffer, 1); goto tilde_input; /*!!*/
case 't' : get_with_expansion("To: ", to, expanded_to); break;
#ifdef ALLOW_BCC
case 'b' : get_with_expansion("Bcc: ", bcc,expanded_bcc); break;
#endif
case 'c' : get_with_expansion("Cc: ", cc, expanded_cc); break;
case 's' : get_with_expansion("Subject: ", subject,NULL); break;
case 'h' : get_with_expansion("To: ", to, expanded_to);
get_with_expansion("Cc: ", cc, expanded_cc);
#ifdef ALLOW_BCC
get_with_expansion("Bcc: ", bcc,expanded_bcc);
#endif
get_with_expansion("Subject: ", subject,NULL); break;
case 'r' : read_in_file(edit_fd, (char *) buffer + 2);
goto more_input;
case 'e' : if (strlen(emacs_editor) > 0)
if (access(emacs_editor, ACCESS_EXISTS) == 0) {
strcpy(buffer, editor);
strcpy(editor, emacs_editor);
fclose(edit_fd);
(void) edit_the_message(filename,0);
Raw(OFF);
strcpy(editor, buffer);
edit_fd = fopen(filename, "a");
printf("(continue entering message, ^D to end)\n");
goto more_input;
}
else
printf(
"(Can't find Emacs on this system! continue)\n");
else
printf(
"(Don't know where Emacs would be...continue)\n");
goto more_input;
case 'v' : strcpy(buffer, editor);
strcpy(editor, default_editor);
fclose(edit_fd);
(void) edit_the_message(filename,0);
Raw(OFF);
strcpy(editor, buffer);
edit_fd = fopen(filename, "a");
printf("(continue entering message, ^D to end)\n");
goto more_input;
case 'o' : printf("Please enter the name of the editor : ");
gets(editor_name);
if (strlen(editor_name) > 0) {
strcpy(buffer, editor);
strcpy(editor, editor_name);
fclose(edit_fd);
(void) edit_the_message(filename,0);
Raw(OFF);
strcpy(editor, buffer);
edit_fd = fopen(filename, "a");
printf("(continue entering message, ^D to end)\n");
goto more_input;
}
printf("(continue)\n");
goto more_input;
case '!' : if (strlen(buffer) < 3)
(void) system_call(shell, USER_SHELL);
else
(void) system_call((char *) buffer+2, USER_SHELL);
printf("(continue)\n");
goto more_input;
case 'm' : /* same as 'f' but with leading prefix added */
case 'f' : /* this can be directly translated into a
'readmsg' call with the same params! */
read_in_messages(edit_fd, (char *) buffer + 1);
goto more_input;
case 'p' : /* print out message so far. Soooo simple! */
print_message_so_far(edit_fd, filename);
goto more_input;
default : printf(
"(don't know what ~%c is. Try ~? for help)\n",
buffer[1]);
}
else
tilde_input:
fprintf(edit_fd, "%s\n", buffer);
};
printf("<end-of-message>\n\n");
Raw(ON);
(void) signal(SIGINT, oldint);
(void) signal(SIGQUIT, oldquit);
if (edit_fd != NULL) /* insurance... */
fclose(edit_fd);
return(0);
}
tilde_help()
{
/* a simple routine to print out what is available at this level */
printf(
"(Available 'tilde' commands at this point are;\n\
\n\
\t~?\tPrint this help menu\n\
\t~~\tAdd line prefixed by a single '~' character\n");
#ifdef ALLOW_BCC
printf("\
\t~b\tChange the addresses in the Blind-carbon-copy list\n");
#endif
printf("\
\t~c\tChange the addresses in the Carbon-copy list\n\
\t~e\tInvoke the Emacs editor on the message, if possible\n\
\t~f\tadd the specified list of messages, or current\n");
#ifdef ALLOW_BCC
printf("\t~h\tchange all available headers (to,cc,bcc,subject)\n");
#endif
printf("\
\t~m\tsame as '~f', but with the current 'prefix'\n\
\t~o\tInvoke a user specified editor on the message\n\
\t~p\tprint out message as typed in so far\n\
\t~r\tRead in the specified file\n\
\t~s\tChange the subject of the message\n\
\t~t\tChange the addresses in the To list\n\
\t~v\tInvoke the Vi visual editor on the message\n\
\t~!\texecute a unix command (or give a shell if no command)\n\
\n");
}
read_in_file(fd, filename)
FILE *fd;
char *filename;
{
/** Open the specified file and stream it in to the already opened
file descriptor given to us. When we're done output the number
of lines we added, if any... **/
FILE *myfd;
char myfname[SLEN], buffer[LONG_SLEN];
register int lines = 0;
while (whitespace(filename[lines])) lines++;
strcpy(myfname, (char *) filename + lines);
if (strlen(myfname) == 0) {
printf("(no filename specified for file read! Continue...)\n");
return;
}
if ((myfd = fopen(myfname,"r")) == NULL) {
printf("(Couldn't open file '%s' for reading! Continue...)\n",
myfname);
return;
}
lines = 0;
while (fgets(buffer, LONG_SLEN, myfd) != NULL) {
lines++;
fputs(buffer, fd);
fflush(stdout);
}
fclose(myfd);
printf("(added %d line%s from file %s. Please continue...)\n",
lines, plural(lines), myfname);
return;
}
print_message_so_far(edit_fd, filename)
FILE *edit_fd;
char *filename;
{
/** This prints out the message typed in so far. We accomplish
this in a cheap manner - close the file, reopen it for reading,
stream it to the screen, then close the file, and reopen it
for appending. Simple, but effective!
A nice enhancement would be for this to -> page <- the message
if it's sufficiently long. Too much work for now, though.
**/
char buffer[LONG_SLEN];
fclose(edit_fd);
if ((edit_fd = fopen(filename, "r")) == NULL) {
printf("\nMayday! Mayday! Mayday!\n");
printf("\nPanic: Can't open file for reading! Bail!\n");
emergency_exit();
}
printf("To: %s\n", format_long(to, 4));
printf("Cc: %s\n", format_long(cc, 4));
#ifdef ALLOW_BCC
printf("Bcc: %s\n", format_long(bcc, 5));
#endif
printf("Subject: %s\n\n", subject);
while (fgets(buffer, LONG_SLEN, edit_fd) != NULL)
printf("%s", buffer);
fclose(edit_fd);
if ((edit_fd = fopen(filename, "a")) == NULL) {
printf("Mayday! Mayday! Abandon Ship! Aiiieeeeee\n");
printf("\nPanic: Can't reopen file for appending!\n");
emergency_exit();
}
printf("(continue entering message, please)\n\n");
}
read_in_messages(fd, buffer)
FILE *fd;
char *buffer;
{
/** Read the specified messages into the open file. If the
first character of "buffer" is 'm' then prefix it, other-
wise just stream it in straight...
**/
FILE *myfd, *popen();
char local_buffer[LONG_SLEN];
register int lines = 0, add_prefix=0;
add_prefix = (tolower(buffer[0]) == 'm');
sprintf(local_buffer, "%s %s", readmsg, ++buffer);
if ((myfd = popen(local_buffer, "r")) == NULL) {
printf("(can't get to 'readmsg' command. Sorry...)\n");
return;
}
while (fgets(local_buffer, LONG_SLEN, myfd) != NULL) {
lines++;
if (add_prefix)
fprintf(fd, "%s%s", prefixchars, local_buffer);
else
fputs(local_buffer, fd);
}
pclose(myfd);
if (lines == 0)
printf("(Couldn't add the requested message. Continue)\n");
else
printf("(added %d line%s to message... Please continue)\n",
lines, plural(lines));
return;
}
get_with_expansion(prompt, buffer, expanded_buffer)
char *prompt, *buffer, *expanded_buffer;
{
/** This is used to prompt for a new value of the specified field.
If expanded_buffer == NULL then we won't bother trying to expand
this puppy out!
**/
char mybuffer[VERY_LONG_STRING];
printf(prompt); fflush(stdout); /* output! */
strcpy(mybuffer, buffer);
Raw(ON);
optionally_enter(buffer, -1, -1, TRUE); /* already data! */
Raw(OFF);
putchar('\n');
if (strcmp(buffer, mybuffer) != 0 && expanded_buffer != NULL)
build_address(strip_commas(buffer), expanded_buffer);
return;
}
edit_interrupt()
{
/** This routine is called when the user hits an interrupt key
while in the builtin editor...it increments the number of
times an interrupt is hit and returns it.
**/
signal(SIGINT, edit_interrupt);
signal(SIGQUIT, edit_interrupt);
if (! interrupts_while_editing++)
printf("(Interrupt. One more to cancel this letter...)\n\r");
longjmp(edit_location); /* get back */
}