static char rcsid[] = "@(#)$Id: answer.c,v 1.23 2006/04/09 07:37:30 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.23 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
/** This program is a phone message transcription system, and
is designed for secretaries and the like, to allow them to
painlessly generate electronic mail instead of paper forms.
Note: this program ONLY uses the local alias file, and does not
even read in the system alias file at all.
**/
#include "elmutil.h"
#include "mailerlib.h"
#include "ndbz.h"
#include "s_answer.h"
#include "sysdefs.h"
#define ELM "elm" /* where the elm program lives */
DBZ *hash; /* dbz file for same */
static int translate P_((char *fullname, char *name, int namesize));
static char *get_alias_address P_((char *name, int mailing, int depth));
static char *get_token P_((char *string, char *sepset, int depth));
static char *quit_word, *exit_word, *done_word, *bye_word;
static void open_alias_file P_((void));
int main P_((int argc, char *argv[]));
int main(argc, argv)
int argc;
char *argv[];
{
FILE *fd;
char *address, buffer[LONG_STRING], tempfile[SLEN], *cp;
char name[SLEN], user_name[SLEN], in_line[SLEN];
int msgnum = 0, eof, allow_name = 0, phone_slip = 0;
int ans_pid = getpid();
#if DEBUG
init_debugfile("ANSWER");
#endif
locale_init();
quit_word = catgets(elm_msg_cat, AnswerSet, AnswerQuitWord, "quit");
exit_word = catgets(elm_msg_cat, AnswerSet, AnswerExitWord, "exit");
done_word = catgets(elm_msg_cat, AnswerSet, AnswerDoneWord, "done");
bye_word = catgets(elm_msg_cat, AnswerSet, AnswerByeWord, "bye");
/*
* simplistic crack arguments, looking for -u/-p
* -u = allow user names not in alias table
* -p = prompt for phone slip messages
*/
for (msgnum = 1; msgnum < argc; msgnum++) {
if (istrcmp(argv[msgnum], "-u") == 0)
allow_name = 1;
if (istrcmp(argv[msgnum], "-p") == 0)
phone_slip = 1;
if (istrcmp(argv[msgnum], "-pu") == 0) {
allow_name = 1;
phone_slip = 1;
}
if (istrcmp(argv[msgnum], "-up") == 0) {
allow_name = 1;
phone_slip = 1;
}
if (strncmp(argv[msgnum], "-d",2) == 0) {
#if DEBUG
set_debugging(argv[msgnum]+2);
#endif
}
}
init_mailerlib();
user_init();
init_defaults();
read_rc_file(0);
elm_sfprintf(version_buff, sizeof version_buff,
FRM("%s PL%s"), VERSION, PATCHLEVEL);
#ifdef DEBUG
{
int d = panic_dprint("\n\
======================================================\n\
Debug output of the ANSWER program (version %s).\n",
version_buff);
if (d >= 50) {
#if 0
panic_dprint("WARNING: Edit manually out sensitive information from that file!\n");
lower_prompt("WARNING: Debug file may include passwords -- edit it!");
sleep(5+sleepmsg);
#endif
}
}
#endif
open_alias_file();
while (1) {
if (msgnum > 9999) msgnum = 0;
printf("\n-------------------------------------------------------------------------------\n");
prompt: elm_fprintf(stdout,
CATGETS(elm_msg_cat, AnswerSet, AnswerMessageTo,
"\nMessage to: "));
if (fgets(user_name, SLEN, stdin) == NULL) {
putchar('\n');
exit(0);
}
if(user_name[0] == '\0')
goto prompt;
cp = &user_name[strlen(user_name)-1];
if(*cp == '\n') *cp = '\0';
if(user_name[0] == '\0')
goto prompt;
if ((istrcmp(user_name, quit_word) == 0) ||
(istrcmp(user_name, exit_word) == 0) ||
(istrcmp(user_name, done_word) == 0) ||
(istrcmp(user_name, bye_word) == 0))
exit(0);
if (translate(user_name, name, sizeof name) == 0)
goto prompt;
address = get_alias_address(name, 1, 0);
if (address == NULL || strlen(address) == 0) {
if (allow_name)
address = name;
else {
printf(catgets(elm_msg_cat, AnswerSet, AnswerSorryNotFound,
"Sorry, could not find '%s' [%s] in list!\n"),
user_name, name);
goto prompt;
}
}
printf("address '%s'\n", address);
elm_sfprintf(tempfile, sizeof tempfile,
FRM("%sans.%d.%d"),
default_temp, ans_pid, msgnum++);
if ((fd = fopen(tempfile,"w")) == NULL) {
lib_error(CATGETS(elm_msg_cat, AnswerSet, AnswerCouldNotOpenWrite,
"** Fatal Error: could not open %s to write\n"),
tempfile);
exit(1);
}
/** Enter standard phone message fields **/
if (phone_slip) {
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet, AnswerCaller,
"Caller: "),
sizeof buffer);
printf("\n%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet, AnswerOf,
"of: "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet, AnswerPhone,
"Phone: "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s\n",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet, AnswerTelephoned,
"TELEPHONED - "),
sizeof buffer);
printf("\n%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet,
AnswerCalledToSeeYou,
"CALLED TO SEE YOU - "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet,
AnswerWantsToSeeYou,
"WANTS TO SEE YOU - "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet,
AnswerReturnedYourCall,
"RETURNED YOUR CALL - "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet, AnswerPleaseCall,
"PLEASE CALL - "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet,
AnswerWillCallAgain,
"WILL CALL AGAIN - "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
strfcpy(buffer, catgets(elm_msg_cat, AnswerSet, AnswerUrgent,
"*****URGENT****** - "),
sizeof buffer);
printf("%s",buffer);
fflush(stdout);
fgets(in_line, SLEN, stdin);
if (strlen(in_line) > 1)
fprintf(fd,"%s%s",buffer,in_line);
}
printf(catgets(elm_msg_cat, AnswerSet, AnswerEnterMessage,
"\n\nEnter message for %s ending with a blank line.\n\n"),
user_name);
fprintf(fd,"\n\n");
do {
printf("> ");
if (! (eof = (fgets(buffer, SLEN, stdin) == NULL)))
fprintf(fd, "%s", buffer);
} while (! eof && strlen(buffer) > 1);
fclose(fd);
elm_sfprintf(buffer, sizeof buffer,
CATGETS(elm_msg_cat, AnswerSet, AnswerElmCommand,
"( ( %s -s \"While You Were Out\" %s < %s ; %s %s) & ) > /dev/null"),
ELM, strip_parens(address), tempfile, remove_cmd, tempfile);
system(buffer);
}
}
static int translate(fullname, name, namesize)
char *fullname, *name;
int namesize;
{
/** translate fullname into name..
'first last' translated to first_initial - underline - last
'initial last' translated to initial - underline - last
Return 0 if error.
**/
register int i, lastname = 0, len;
for (i=0, len = strlen(fullname); i < len; i++) {
#ifdef ASCII_CTYPE
if (isascii(fullname[i]))
#endif
fullname[i] = tolower(fullname[i]);
if (fullname[i] == ' ')
if (lastname) {
lib_error(CATGETS(elm_msg_cat, AnswerSet, AnswerCannotHaveMoreNames,
"** Can't have more than 'FirstName LastName' as address!\n"));
return(0);
}
else
lastname = i+1;
}
if (lastname)
elm_sfprintf(name, namesize,
FRM("%c_%.*s"),
fullname[0], namesize-4, (char *) fullname + lastname);
else
strfcpy(name, fullname, namesize);
return(1);
}
static void open_alias_file()
{
/** open the user alias file **/
char fname[SLEN];
strfcpy(fname,user_data_file,sizeof fname);
if ((hash = dbz_open(fname, O_RDONLY, 0)) == NULL)
exit(printf("** Fatal Error: Could not open %s!\n", fname));
}
static int expand_group P_((
char *target,
char *members,
int depth,
int targetsize));
static char *get_alias_address P_((char *name,
int mailing, int depth));
static char *get_alias_address(name, mailing, depth)
char *name;
int mailing, depth;
{
/** return the line from either datafile that corresponds
to the specified name. If 'mailing' specified, then
fully expand group names. Returns NULL if not found.
Depth is the nesting depth, and varies according to the
nesting level of the routine. **/
static char sprbuffer[VERY_LONG_STRING];
int loc;
struct alias_rec *entry1;
entry1 = fetch_alias(hash,name);
if (entry1 == NULL)
return( NULL); /* not found */
if ((entry1->type & GROUP) != 0 && mailing) {
if (expand_group(sprbuffer, entry1->address,
depth, sizeof sprbuffer) < 0) {
free(entry1);
return NULL;
}
} else {
elm_sfprintf(sprbuffer, sizeof sprbuffer,
FRM("%s (%s)"),
entry1->address,
entry1->name);
}
free(entry1);
return sprbuffer;
}
static int expand_group(target, members, depth, targetsize)
char *target;
char *members;
int depth;
int targetsize;
{
/** given a group of names separated by commas, this routine
will return a string that is the full addresses of each
member separated by spaces. Depth is the current recursion
depth of the expansion (for the 'get_token' routine) **/
char buf[VERY_LONG_STRING], *word, *address, *bufptr;
strfcpy(buf, members, sizeof buf); /* parameter safety! */
target[0] = '\0'; /* nothing in yet! */
bufptr = (char *) buf; /* grab the address */
depth++; /* one more deeply into stack */
while ((word = (char *) get_token(bufptr, "!, ", depth)) != NULL) {
if ((address = (char *) get_alias_address(word, 1, depth)) == NULL) {
lib_error(CATGETS(elm_msg_cat, AnswerSet, AnswerNotFoundForGroup,
"Alias %s not found for group expansion!\n"),
word);
return -1;
}
else if (strcmp(target,address) != 0) {
elm_sfprintf(target + strlen(target), targetsize - strlen(target),
FRM(" %s"),
address);
}
bufptr = NULL;
}
return 0;
}
/****
The following is a newly chopped version of the 'strtok' routine
that can work in a recursive way (up to 20 levels of recursion) by
changing the character buffer to an array of character buffers....
****/
#define MAX_RECURSION 20 /* up to 20 deep recursion */
#undef NULL
#define NULL (char *) 0 /* for this routine only */
static char *get_token(string, sepset, depth)
char *string, *sepset;
int depth;
{
/** string is the string pointer to break up, sepstr are the
list of characters that can break the line up and depth
is the current nesting/recursion depth of the call **/
register char *p, *q, *r;
static char *savept[MAX_RECURSION];
/** is there space on the recursion stack? **/
if (depth >= MAX_RECURSION) {
fprintf(stderr, catgets(elm_msg_cat, AnswerSet, AnswerRecursionTooDeep,
"Error: Get_token calls nested greater than %d deep!\n"),
MAX_RECURSION);
exit(1);
}
/* set up the pointer for the first or subsequent call */
p = (string == NULL)? savept[depth]: string;
if(p == 0) /* return if no tokens remaining */
return(NULL);
q = p + strspn(p, sepset); /* skip leading separators */
if (*q == '\0') /* return if no tokens remaining */
return(NULL);
if ((r = strpbrk(q, sepset)) == NULL) /* move past token */
savept[depth] = 0; /* indicate this is last token */
else {
*r = '\0';
savept[depth] = ++r;
}
return(q);
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1