static char rcsid[] = "@(#)$Id: read_rc.c,v 1.183 2006/06/25 10:41:04 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.183 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
* or Kari Hurtta <elm@elmme-mailer.org>
*****************************************************************************
*
* Most of code copied from ../src/read_rc.c. It have following copyright:
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
#define SAVE_OPTS
#include "headers.h"
#include "rc_imp.h"
#include "save_opts.h"
#include "s_elm.h"
#include "s_me.h"
#include "unidata.h"
#include "cs_imp.h"
#include "patchlevel.h"
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
DEBUG_VAR(Debug,__FILE__,"config");
#ifdef PWDINSYS
# include <sys/pwd.h>
#else
# include <pwd.h>
#endif
#ifndef I_UNISTD
char *getlogin();
unsigned short getgid(), getuid();
struct passwd *getpwuid();
#endif
# ifdef DOUNAME
# include <sys/utsname.h>
# endif
struct hist_record {
char *tag;
struct rc_save_info_rec * entry;
int changed;
char ** old_line;
int line_count;
};
static struct elmrc_recorder {
struct hist_record *recs;
int rec_count;
} * recorders[RC_MODE_COUNT];
struct elmrc_recorder * enable_recorder(mode)
enum record_mode mode;
{
if (mode < 0 || mode >= RC_MODE_COUNT)
panic("RC PANIC",__FILE__,__LINE__,"enable_recorder",
"Bad mode",0);
if (! recorders[mode] ) {
struct elmrc_recorder * X;
X = safe_malloc(sizeof (*X));
bzero((void *)X, sizeof (* (X)));
X->recs = NULL;
X->rec_count = 0;
recorders[mode] = X;
}
return recorders[mode];
}
static struct hist_record * record1 P_((struct elmrc_recorder *recorder,
struct rc_save_info_rec *X,
char *tag));
static struct hist_record * record1(recorder,X,tag)
struct elmrc_recorder *recorder;
struct rc_save_info_rec *X;
char *tag;
{
struct hist_record *r;
recorder->recs = safe_realloc(recorder->recs,
sizeof (recorder->recs[0]) *
( recorder->rec_count + 1 ));
r = & (recorder->recs[recorder->rec_count]);
bzero((void *)r, sizeof (*r));
r->entry = X;
r->tag = NULL;
if (tag)
r->tag = safe_strdup(tag);
r->old_line = 0;
r->line_count = 0;
r->changed = 0;
recorder->rec_count++;
return r;
}
static struct hist_record * need_record P_((enum record_mode mode,
struct rc_save_info_rec *X,
char *tag));
static struct hist_record * need_record(mode,X,tag)
enum record_mode mode;
struct rc_save_info_rec * X;
char *tag;
{
int i;
struct hist_record *r;
if (! recorders[mode] )
return NULL;
/* If old value is already recorded,
do not add 'new' old value
*/
for (i = 0; i < recorders[mode]->rec_count; i++)
if (recorders[mode]->recs[i].entry == X)
return NULL;
return record1(recorders[mode],X,tag);
}
static char * split_keyword P_((char *buffer, int line_len,
char *keyword, int size,
char **tag,
int *assig));
static struct rc_save_info_rec *locate_option P_((struct rc_save_info_rec * rc_options,
int rc_option_count,
char *word1,
char *word2,
char *filename,
int *negate));
#define MAX_LINE 10000
int seed_history(F,filename,recorder)
FILE *F;
char * filename;
struct elmrc_recorder *recorder;
{
int ok = 1;
char * buffer = NULL;
int r; /* length of line or error/eof status */
int lineno = 0;
char current_tag[SLEN];
struct rc_save_info_rec * prev_type = NULL;
struct hist_record * rec = NULL;
int ignored = 0;
current_tag[0] = '\0';
/* malloc_gets does realloc, so buffer need not
be freed on loop
*/
while (0 <= ( r = malloc_gets(&buffer,MAX_LINE,F))) {
char * tag = NULL;
char keyword[SLEN], *c;
char * rest = NULL;
int assig = 0;
int negate = 0;
lineno++;
if (!buffer) /* EOF */
break;
if (buffer[0] == '#' /* comment */
|| r < 1) /* empty line */
continue;
rest = split_keyword(buffer,r,keyword, sizeof keyword,
&tag,&assig);
if (tag && !keyword[0]) {
strfcpy(current_tag, tag, sizeof current_tag);
if (rest[0] && '#' != rest[0]) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmIgnoredLine,
"Rest of line ignored after \"%s:\" on line %d on file %s"),
tag, lineno,filename);
ok = 0;
}
} else if (!keyword[0]) {
if (prev_type != NULL) {
if (RCTYPE_magic != prev_type->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"do_rc",
"Bad prev_type",0);
if (rec) {
rec->old_line = safe_realloc(rec->old_line,
sizeof(rec->old_line[0]) *
( rec->line_count + 1));
rec->old_line [ rec->line_count ] = safe_strdup(rest);
rec->line_count++;
/* Preserve seeded data when printing again */
rec->changed++;
}
}
} else if (assig) {
if (tag || current_tag[0]) {
struct rc_save_info_rec * rc_options = NULL;
int rc_option_count = 0;
if (!tag)
tag = current_tag;
else
ignored = 0;
#ifdef USE_DLOPEN
if (give_options(tag,&rc_options,&rc_option_count)) {
prev_type = locate_option(rc_options,rc_option_count,
keyword,rest,filename,
&negate);
ignored = 0;
if (!prev_type) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadKeyTagInElmrc,
"I can't understand keyword \"%s\" (section %s) in line %d in \"%s\" file"),
keyword, tag,lineno,filename);
ok = 0;
continue;
}
} else if (!ignored) {
ignored = 1;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmIgnoredSection,
"Keywords on section \"%s\" ignored starting from line %d on file %s"),
tag, lineno,filename);
ok = 0;
}
#else
if (!ignored) {
ignored = 1;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmSharedIgnoredSection,
"Shared libraries not supported. Section \"%s\" ignored starting from line %d on file %s"),
tag, lineno,filename);
ok = 0;
}
#endif
} else {
prev_type = locate_option(save_info,NUMBER_OF_SAVEABLE_OPTIONS,
keyword,rest,filename,&negate);
if (!prev_type) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadKeyInElmrc,
"I can't understand keyword \"%s\" in line %d in \"%s\" file"),
keyword, lineno,filename);
ok = 0;
continue;
}
}
rec = record1(recorder,prev_type,tag);
if (rec) {
if (rec->line_count)
panic("RC PANIC",__FILE__,__LINE__,"do_rc",
"Bad prev_type",0);
rec->old_line = safe_malloc(sizeof(rec->old_line[0]));
rec->old_line[0] = safe_strdup(rest);
rec->line_count = 1;
rec->changed++;
}
} else {
prev_type = NULL;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadLineInElmrc,
"Keyword \"%s\" without = -character in line %d in \"%s\" file"),
keyword, lineno,filename);
ok = 0;
}
}
if (-1 == r) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTooLongLine,
"%.30s: %d: Too long line: %.30s..."),
filename,lineno+1,
buffer ? buffer : "<not available>");
ok = 0;
}
if (ferror(F)) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorReading,
"Error reading from %.50s"),
filename);
ok = 0;
}
if (buffer)
free(buffer);
return ok;
}
static void print_history_record P_((FILE *F,struct hist_record *x));
static void print_history_record(F,x)
FILE *F;
struct hist_record *x;
{
int i;
fprintf(F,"\n%s = %s\n",
x->entry->name,
x->old_line[0]);
for (i = 1; i < x->line_count; i++) {
fprintf(F,"\t%s\n",
x->old_line[i]);
}
}
void print_history_changed(F,recorder)
FILE *F;
struct elmrc_recorder *recorder;
{
int i;
/* First print lines without tag */
char * last_tag = NULL;
for (i = 0; i < recorder->rec_count; i++) {
if (recorder->recs[i].changed &&
NULL == recorder->recs[i].tag) {
print_history_record(F,& (recorder->recs[i]));
}
}
/* Then print values with tag */
for (i = 0; i < recorder->rec_count; i++) {
if (recorder->recs[i].changed &&
NULL != recorder->recs[i].tag) {
if (!last_tag ||
0 != strcmp(last_tag,
recorder->recs[i].tag)) {
last_tag = recorder->recs[i].tag;
fprintf(F,"\n\n%s:\n",
last_tag);
print_history_record(F,& (recorder->recs[i]));
}
}
}
}
void mark_XX(x)
struct rc_save_info_rec *x;
{
enum record_mode mode;
int found = 0;
x->flags |= FL_LOCAL;
x->flags |= FL_CHANGED;
DPRINT(Debug,10,(&Debug,
"mark_XX: Setting %p %s changed\n",
x,x->name));
for (mode = SYSTEM_RC; mode < RC_MODE_COUNT; mode++) {
if (recorders[mode]) {
int i;
for (i = 0; i < recorders[mode]->rec_count; i++)
if (recorders[mode]->recs[i].entry == x) {
recorders[mode]->recs[i].changed++;
found++;
DPRINT(Debug,10,(&Debug,
"mark_XX: recorders[%d]->recs[%d].entry == %p\n",
mode,i,x));
}
} else {
DPRINT(Debug,10,(&Debug,
"mark_XX: no mode=%d\n",mode));
}
}
if (!found) {
DPRINT(Debug,10,(&Debug,
"mark_XX: no change record\n"));
}
}
void mark_local_changed(A)
void *A;
{
int x;
for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
if (save_info[x].val.dummy == A) {
DPRINT(Debug,10,(&Debug,
"mark_local_changed: %d: %p\n",
x,A));
mark_XX(& (save_info[x]));
}
}
#ifdef USE_DLOPEN
mark_shared_changed(A);
#endif
mark_delayed_changed(A);
}
void mark_flocal_changed(A)
option_func *A;
{
int x;
for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
if (save_info[x].func_val == A) {
DPRINT(Debug,10,(&Debug,
"mark_flocal_changed: %d: %p\n",
x,A));
mark_XX(& (save_info[x]));
}
}
#ifdef USE_DLOPEN
mark_fshared_changed(A);
#endif
mark_fdelayed_changed(A);
}
#ifdef HAVE_CODESET
#include <langinfo.h>
#endif
static int lineno = 0;
static int errors = 0;
static void do_expand_env P_((char *, char *, char *, unsigned));
static void do_rc P_((FILE *file,enum record_mode lcl, char *filaname));
int parse_elmrc(F,global,filename)
FILE *F;
int global;
char *filename;
{
errors = 0;
do_rc(F, global ? SYSTEM_RC : LOCAL_RC, filename);
return errors;
}
#ifndef ok_rc_char
#define ok_rc_char(c) (isalnum(c) || c == '-' || c == '_')
#endif
char system_text_file[SLEN] = SYSTEM_TEXT_FILE;
char system_data_file[SLEN] = SYSTEM_DATA_FILE;
char system_rc_file[SLEN] = SYSTEM_RC_FILE;
char system_mime_types[SLEN] = SYSTEM_MIME_TYPES;
char system_iso2022_sets[SLEN] = SYSTEM_ISO2022_SETS;
char system_terminal_info[SLEN] = SYSTEM_TERMINAL_INFO;
char system_mail_services[SLEN] = SYSTEM_MAIL_SERVICES;
char hostdomfile[SLEN] = HOSTDOMFILE;
char system_mime_charsets[SLEN] = SYSTEM_MIME_CHARSETS;
ESTR map_txtdir_e = { /* init_defaults */
ESTR_meta|ESTR_slash,
NULL,
NULL
};
ESTR map_bindir_e = { /* init_defaults */
ESTR_meta|ESTR_slash,
NULL,
NULL
};
char unidata_path[SLEN] = {0}; /* init_defaults */
char raw_unidata_path[SLEN] = "unidata.bin"; /* init_defaults */
char bindata_path_global[SLEN] = {0}; /* Used before user elm.rc is read */
char bindata_path[SLEN] = {0}; /* init_defaults */
char raw_bindata_path[SLEN] = "bindata.bin"; /* init_defaults */
int unstable_reverse_thread = 0;
char user_rc_file[SLEN] = ELMRCFILE; /* user_init fixes */
char user_text_file[SLEN] = USER_ALIAS_TEXT; /* user_init fixes */
char user_data_file[SLEN] = USER_ALIAS_DATA; /* user_init fixes */
char user_mime_types[SLEN] = USER_MIME_TYPES; /* user_init fixes */
char user_mailheaders[SLEN] = MAILHEADERS; /* user_init fixes */
char user_mime_charsets[SLEN] = USER_MIME_CHARSETS; /* user_init fixes */
char user_iso2022_sets[SLEN] = USER_ISO2022_SETS; /* user_init fixes */
char user_terminal_info[SLEN] = USER_TERMINAL_INFO; /* user_init fixes */
char user_mail_services[SLEN] = USER_MAIL_SERVICES; /* user_init fixes */
ESTR defaultfile_e = { /* name of default folder */
0,
NULL,
NULL
};
ESTR calendar_file_e = { /* name of file for clndr */
0,
NULL,
NULL
};
ESTR dead_letter_dir_e = {
0,
NULL,
NULL
};
int clear_pages = 0; /* flag: act like "page" (more -c)? */
int title_messages = 1; /* flag: title message display? */
nl_catd elm_msg_cat = 0; /* message catalog */
/* WARNING: Elm's version uses 0 as failure
System uses (nl_catd) -1 as failure !
*/
char username[SLEN] = {0}; /* return address name! */
char home[SLEN] = {0}; /* home directory of user */
int userid = -1; /* uid for current user */
int groupid = -1; /* groupid for current user */
int mailgroupid; /* groupid for current user */
int have_saved_ids = 0; /* sysconf _SC_SAVED_IDS */
/* ------------- Variables in elmrc ------------------------------- */
int add_irt_phrase = 0; /* In-reply-to: Add phare to in-reply-to ?
True = Do not follow RFC 2822
*/
int add_sender_header = 1; /* If set add Sender: header if user specifies
From: -header
*/
int allow_charset_switching=0; /* flag: allow changing charset of */
/* terminal if terminal supports */
static struct sortval ASR_srtval[]={
{"alias", ALIAS_SORT},
{"name", NAME_SORT},
{"text", TEXT_SORT},
{NULL, 0}
};
SORT alias_sortby = { /* how to sort aliases... */
NAME_SORT,
ASR_srtval
};
char alternative_editor[SLEN] = "EDITOR"; /* alternative editor... */
PATH alternative_addresses = { /* how else do we get mail? */
PATH_sep_comma,
NULL, 0,NULL
};
int always_del = 0; /* flag: always delete marked msgs? */
int always_keep = 1; /* flag: always keep unread msgs? */
int always_store = 0; /* flag: always store read msgs? */
int arrow_cursor = 0; /* flag: use "->" cursor regardless?*/
int question_me = 1; /* flag: ask questions as we leave? */
int prompt_for_cc = 1; /* flag: ask user for "cc:" value? */
#ifdef USE_PGP
int pgp_askpgpsig=0; /* Should pgp ask userid to sign messages with? */
static char * PGP_SIGN_TYPES[] = { "application/pgp", "text/plain",
"text/x-pgp", NULL };
ENUMERATE pgp_sign_type= { /* 0 = application/pgp */
0, /* 1 = text/plain */
3, &(PGP_SIGN_TYPES[0]) /* 2 = text/x-pgp */
};
static char * PGP_ENCRYPT_TYPES[] = { "application/pgp", "text/plain",
"text/x-pgp", NULL };
ENUMERATE pgp_encrypt_type= { /* 0 = application/pgp */
0, /* 1 = text/plain */
3, &(PGP_ENCRYPT_TYPES[0]) /* 2 = text/x-pgp */
};
int pgp_interactive=0; /* Should pgp/gpg encryption/signing to be
run always on interactive mode */
static char * PGP_VERSIONS[] = { "default", "pgp2", "pgp5", "gpg", NULL };
ENUMERATE send_pgp_version = { /* preferred pgp version*/
pgp_none,
4, &(PGP_VERSIONS[0])
};
#endif
char attribution[SLEN] = {0}; /* attribution string for replies */
static char * AUTO_ATTACH[] = { "none", "application", "non-text", NULL };
ENUMERATE auto_attachment = { /* 0 = none, */
1, /* 1 = application, */
3, &(AUTO_ATTACH[0]) /* 2 = non-text */
};
int auto_copy = 0; /* flag: automatically copy source? */
int auto_iso_8859 = 1; /* flag: Should ISO-8859-X charsets defined
on demand ? */
#ifdef BACKGROUD_PROCESSES
int background_wait_time = 2; /* If > 0 background mailer after */
/* this number of seconds */
#endif
int browser_wildcards = 1; /* flag: do wildcard match? */
int builtin_lines= -3; /* int: if < 0 use builtin if message*/
/* shorter than LINES+builtin_lines */
/* else use pager. If > 0 use builtin*/
/* if message has fewer than # of lines*/
int charset_convert_ok = 0; /* flag: no warning about conversion? */
int check_type_pattern = 1; /* flag: check magic numbers when paging */
char raw_text_charset[SLEN] = "DISPLAY"; /* name of character set */
charset_t text_charset = NULL; /* pointer of character set */
char raw_default_mimetext_charset[SLEN] = "US-ASCII";
/* name of character set */
charset_t default_mimetext_charset = NULL; /* pointer to character set */
char raw_default_nomime_charset[SLEN] = "SYSTEM"; /* name of character set */
charset_t default_nomime_charset = NULL; /* pointer to character set */
static char * FOLDER_STATUS[] = { "Read", "Old", "New", NULL };
ENUMERATE def_folder_status = { /* 0 = Read */
FOLDER_STATUS_OLD, /* 1 = Old */
3, &(FOLDER_STATUS[0]) /* 2 = New */
};
char config_options[SLEN] = {0};/* which options are in o)ptions */
int confirm_append = 0; /* flag: confirm append to folder? */
int confirm_create = 0; /* flag: confirm create new folder? */
int confirm_files = 0; /* flag: confirm files for append? */
int confirm_folders = 0; /* flag: confirm folders for create?*/
int convert_comment = 1; /* flag: convert comment to fullname ? */
int convert_utf_header = 1; /* flag: convert utf-8 mime encoded words to utf-7 when sending? */
int auto_copy_sent = -1; /* flag: automatically copy sent mail? */
char display_locale[SLEN] = "NONE"; /* LC_CTYPE locale (character set) */
char display_codeset[SLEN] = ""; /* nl_langinfo(CODESET) for current locale (character set) */
charset_t wanted_display_charset = NULL;
char raw_display_charset[SLEN] = "SYSTEM";
/* the wanted display charset set */
int DSN_success = 0; /* flag: Ask successfull DSNes */
char e_editor[SLEN] = {0}; /* "~e" editor... */
ESTR editor_e = { /* editor for outgoing mail*/
0,
NULL,
NULL
};
static char * MPAR[] = { "plain", "encoded", "plain-and-encoded" };
ENUMERATE mime_parameters = {
2,
3, &(MPAR[0])
};
static char * ENV_FROM_SOURCES[] = { "forward-from", "from", "return-path",
NULL };
ENUMERATE env_from_source = { /* 0 == forward-from, */
0, /* 1 == from, */
3, &(ENV_FROM_SOURCES[0]) /* 2 == return-path */
};
char escape_char = TILDE_ESCAPE;/* '~' or something else.. */
int force_name = 0; /* flag: save by name forced? */
static char * FRAGMENTH_list[] = { "none", "manual", "auto" };
ENUMERATE fragment_handling = { /* 0 == none, */
1, /* 1 == manual, */
3, &(FRAGMENTH_list[0]) /* 2 == auto */
};
int allow_forms = NO; /* flag: are AT&T Mail forms okay? */
char full_username[SLEN] = {0}; /* Full username - gecos */
static char * HDR_PHRASE_DISPLAY_MODES[] = { "plain", "quoted", NULL };
ENUMERATE phrase_display_mode = { /* 0 == plain, 1 = quoted */
0,
2, &(HDR_PHRASE_DISPLAY_MODES[0])
};
char hostdomain[SLEN] = {0}; /* name of domain we're in */
char hostfullname[SLEN] = {0}; /* name of FQDN we're in */
char hostname[SLEN] = {0}; /* name of machine we're on */
#ifdef DISP_HOST
int menu_display_host = TRUE; /* flag: Display host on mailbox menu* */
#else
int menu_display_host = FALSE; /* flag: Display host on mailbox menu? */
#endif
int keep_empty_files = 0; /* flag: leave empty folder files? */
#ifdef USE_PGP
int pgp_keeppassfor = 300; /* 5 minutes */
#endif
static struct sortval DIR_srtval[]={
{"none", LD_NONE},
{"name", LD_NAME_SORT},
{"mtime", LD_MTIME_SORT},
{NULL, 0}
};
SORT local_dir_sortby = { /* how to sort files... */
LD_NAME_SORT,
DIR_srtval
};
int local_fast_lookup = 0; /* flag: directory listing not needed
for lookup */
char local_sessionlock_dir[SLEN] = default_temp;
static char * LSL_list[] = { "never", "spool", "always", "non-spool", NULL };
ENUMERATE local_sessionlock_use_home = { /* 0 == newer, */
0, /* 1 == spool */
4, &(LSL_list[0]) /* 2 == always */
}; /* 3 == non-spool */
char raw_local_fs_charset[SLEN] = "SYSTEM"; /* filesystem charset */
charset_t local_fs_charset = NULL; /* filesystem charset */
ESTR local_signature_e = { /* local msg signature file */
0,
NULL,
NULL
};
/* signature file */
#if defined(WCHAR) && defined(__STDC_ISO_10646__)
PATH locale_charsets= { /* Use type=unknown for these charsets
* if system charset
*/
0, /* flags */
NULL , 0, NULL
};
#endif
#ifdef SYSCALL_LOCKING
int lockfolders = 1; /* Lock folder when open */
int lock_in_copy = 1; /* Lock folder when copied to it */
#else
int lockfolders = 0; /* Lock folder when open */
int lock_in_copy = 0; /* Lock folder when copied to it */
#endif
int long_encoded_headers = 1; /* Produce over 80 character mime encoded
headers */
ESTR folders_e = { /* folder home directory */
ESTR_slash,
NULL,
NULL
};
ESTR extra_mailbox_dir_e = {
ESTR_slash,
NULL,
NULL
};
ESTR attachment_dir_e = { /* {doc} -prefix */
0, /* Note that default assigment do not add / to end */
NULL,
NULL
};
int attachment_fix_extension = 1; /* flag: fix extension of attashment when saving */
int mail_permissions = 0600; /* int: permissions for mailbox files */
int mini_menu = 1; /* flag: menu specified? */
static char * hide_hacks[] = { "none", "FOLDER INTERNAL DATA", NULL };
ENUMERATE message_hide_hack = { /* 0 == none */
0, /* 1 = FOLDER INTERNAL DATA */
2, &(hide_hacks[0])
};
ESTR metamail_path_e = { /* Metamail path or "none" */
ESTR_none|ESTR_metamail, /* if no metamail */
NULL,
NULL
};
PATH metamail_mailcaps = { /* mailcaps for metamail */
PATH_file|PATH_sep_colon|PATH_expand,
NULL, 0,NULL
};
PATH internal_mailcaps = { /* mailcaps for internal handler */
PATH_file|PATH_sep_colon|PATH_expand,
NULL, 0,NULL
};
PATH internal_mailcap_t_programs = {
0,
NULL, 0, NULL
};
int internal_mailcap_t_prompt = 0;
int metoo = 0; /* flag: copy me on mail to alias? */
int mime_body_keywords = TRUE; /* flag: parse body looking for encode */
/* keywords */
int mimeforward = FALSE; /* flag: Forward as Message/rfc822 */
int askmimeforward = 1; /* flag: prompt about messaga/rfc822 forward */
int move_when_paged = 0; /* flag: move when '+' or '-' used? */
int names_only = 0; /* flag: display user names only? */
static char * NOENCODINGS[] = { "pass-7bit", "pass-8bit", "pass-binary",
NULL };
ENUMERATE allow_no_encoding = { /* 1: Allow 8bit without -B8BITMIME */
0, /* 2: Allow binary without -BBINARYMIME and */
3, &(NOENCODINGS[0]) /* and 8bit without -B8BITMIME */
};
int allow_no_hdrencoding = 0; /* TRUE, if header encoding is */
/* not required */
int noheader = 1; /* flag: copy + header to file? */
int noheaderfwd = 0; /* flag: copy + header to file(fwd)? */
int pagealternative=1; /* Page if alternative have one know*/
/* subtype ? */
int page_known_charsets=1; /* Page if charset is not unknown? */
int pagemultipart=0; /* Page unknown mime subparts? */
int pagesigned=0; /* Page unknown signed protocols? */
ESTR pager_e = { /* what pager to use */
0,
NULL,
NULL
};
char pager[SLEN] = {0}; /* what pager to use */
char raw_pager[SLEN] = {0}; /* unexpanded what pager to use */
#ifdef USE_PGP
ESTR pgp2_path_e = { /* Pgp path or "none" if no pgp */
ESTR_none,
NULL,
NULL
};
ESTR pgp5_dir_e = { /* pgp5 binary directory or "none" if no pgp5 */
ESTR_slash|ESTR_none,
NULL,
NULL
};
ESTR gpg_path_e = {
ESTR_none,
NULL,
NULL
};
#endif
int point_to_new = 1; /* flag: start pointing at new msg? */
char allowed_precedences[SLEN] = {0}; /* list of precedences user */
/* may specify */
char prefixchars[SLEN] = "> "; /* prefix char(s) for msgs */
ESTR printout_e = { /* how to print messages */
ESTR_none,
NULL,
NULL
};
int prompt_after_pager = 1; /* flag: prompt after pager exits */
int prompt_after_metamail = 1; /* flag: prompt after metamail exits */
int prompt_metamail = 1; /* flag: prompt for calling of metamil */
int quote_forward = 0; /* flag: fwd'd msgs quoted like replies */
int readdatapercentinc = 5; /* data percent increment during new mbox read */
ESTR readmsg_e = { /* path to readmsg program */
ESTR_meta,
NULL,
NULL
};
int readmsginc = 100; /* increment of msg cnt when reading*/
/* new mbox */
ESTR recvd_mail_e = { /* folder for storing received mail */
ESTR_none|ESTR_meta,
NULL,
NULL
};
ESTR remote_signature_e = { /* remote msg signature file */
0,
NULL,
NULL
};
int req_mime_bodyencoding = 1; /* */
int req_mime_hdrencoding = 0; /* */
int resolve_mode = 1; /* flag: delete saved mail? */
int save_by_name = 1; /* flag: save mail by login name? */
ESTR sent_mail_e = { /* name of file to save copies to */
ESTR_none|ESTR_meta,
NULL,
NULL
};
int send_mime_plain = 1; /* flag: send plain text as MIME? */
ESTR shell_e = { /* current system shell */
ESTR_bin,
NULL,
NULL
};
int set_window_title = 0; /* flag: set (xterm?) window title and
icon name */
#ifdef USE_PGP
int pgp_noarmor=1; /* Should Elm display text before PGP armor */
#endif
int showto = 0; /* */
static char * HEADER_ERROR_MODES[] =
{ "OFF", "ON", "store", NULL };
ENUMERATE show_header_errors_e = {
2,
3, &(HEADER_ERROR_MODES[0]),
};
int sig_dashes = 1; /* flag: include dashes above sigs? */
int sleepmsg = 2; /* time to sleep for messages being */
/* overwritten on screen */
static struct sortval SRT_srtval[]={
{"sent", SENT_DATE},
{"thread", THREAD},
{"received", RECEIVED_DATE},
{"recieved", RECEIVED_DATE},
{"rec", RECEIVED_DATE},
{"from", SENDER},
{"sender", SENDER},
{"size", SIZE},
{"lines", SIZE},
{"subject", SUBJECT},
{"mailbox", MAILBOX_ORDER},
{"folder", MAILBOX_ORDER},
{"status", STATUS},
{NULL, 0}
};
SORT sortby = { /* how to sort incoming mail... */
REVERSE SENT_DATE,
SRT_srtval
};
static struct sortval THREAD_srtval[]={
{"sent", SENT_DATE},
{"subject", SUBJECT},
{NULL, 0}
};
SORT thread_sortby = { /* how to sort threads of messages */
REVERSE SENT_DATE,
THREAD_srtval
} ;
long elm_timeout = 600L; /* timeout (secs) on main prompt */
int sort_thread_max_time = 30; /* Number of days which can considered
be same thread */
ESTR temp_dir_e = { /* name of temp directory */
ESTR_slash,
NULL,
NULL
};
#ifdef USE_PGP
int pgp_keeppass=0; /* should Elm keep the passphrase in*/
/* memory? */
#endif
static char * USERLEVELS[] = { "beginner", "intermediate", "expert", NULL };
ENUMERATE user_level = { /* flag: how good is the user? */
0,
3, &(USERLEVELS[0])
};
int use_tite = 1; /* flag: use termcap/terminfo ti/te?*/
int utf7_encode_optional = 1; /* flag: Should utf7 optional direct
characters to be encoded? */
#ifdef I_NETDB
int verify_domain = 0; /* flag: Should we try check existence
of mail domain
*/
#endif
int verify_local_address = 0; /* flag: Should we try check existence
of local user
*/
char v_editor[SLEN] = {0}; /* "~v" editor... */
int elm_filter = 1; /* flag: weed out header lines? */
PATH weedlist = {
PATH_sep_comma|PATH_quote|PATH_convert_underline,
NULL, 0,NULL
};
#ifdef REMOTE_MBX
static struct sortval IMAP_srtval[]={
{"none", ID_NONE},
{"name", ID_NAME_SORT},
{NULL, 0}
};
SORT imap_dir_sortby = { /* how to sort imap folders... */
ID_NONE,
IMAP_srtval
};
char raw_imap_charset[SLEN] = "SYSTEM"; /* IMAP foldername charset */
int imap_fast_lookup = 0; /* flag: skip some directory listing */
int imap_max_dl_size = 4*1024; /* Maximum size of message to be
* downloaded
*/
charset_t imap_charset = NULL; /* IMAP foldername charset */
int IMAP_connection_cache = 1; /* flag: call cache_connection() ? */
int IMAP_name_convention = 1; /* flag: Should imap intearnational folder
convention be used? */
int IMAP_use_examine = 1; /* flag: Should EXAMINE command to be used? */
int IMAP_show_greeting = 1; /* flag: Should untagged OK messages be shown? */
int IMAP_show_warning = 1; /* flag: Should untagged NO messages be shown? */
int IMAP_show_error = 1; /* flag: Should untagged BAD messages be shown? */
int pop_max_dl_size = 4*1024; /* Maximum size of message to be
* downloaded
*/
int POP_show_greeting = 1; /* flag: Should POP server greeting be shown? */
#endif
/* ---------------------------------------------------------------- */
static void do_expand_env P_((char *descr, char *dest, char *src,
unsigned destlen));
static void do_expand_env(descr, dest, src, destlen)
char *descr, *dest, *src;
unsigned destlen;
{
if (expand_env(dest, src, destlen) != 0) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCannotInitErrorExpanding,
"Cannot initialize \"%s\" - error expanding \"%s\"."),
descr, src);
errors++;
dest[0] = '\0';
}
}
static void do_expand_meta P_((char *descr, char *dest, char *src,
unsigned destlen));
static void do_expand_meta(descr, dest, src, destlen)
char *descr, *dest, *src;
unsigned destlen;
{
if (expand_meta(dest, src, destlen) != 0) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCannotInitErrorExpanding,
"Cannot initialize \"%s\" - error expanding \"%s\"."),
descr, src);
errors++;
dest[0] = '\0';
}
}
static void expand_map_bin P_((char *descr, char *dest, char *src,
unsigned destlen));
static void expand_map_bin(descr, dest, src, destlen)
char *descr, *dest, *src;
unsigned destlen;
{
if (strcmp(src,"none") == 0 || src[0] == '\0') {
strfcpy(dest,"none",destlen);
} else if (NULL == strpbrk(src,"/$\\;{}()")) {
/* give_dt_estr_as_str adds / to end */
char * map_bindir_val = give_dt_estr_as_str(&map_bindir_e,
"map-bin-dir");
if (!map_bindir_val) {
dest[0] = '\0';
return;
}
if (0 != access(map_bindir_val,ACCESS_EXISTS)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, ElmSet,ElmNoBinMapDirX,
"%s: no map-bin-dir exist: %s: %s"),
descr,
map_bindir_val,error_description(err));
/* No error counter incrementging because
map-bin-dir can be modified only on system
elm.rc
*/
}
elm_sfprintf(dest,destlen,
FRM("%s/%s"),
map_bindir_val,src);
} else
do_expand_meta(descr, dest, src, destlen);
DPRINT(Debug,10,(&Debug, "%s expanded: %s => %s (destlen %d)\n",
descr,src,dest,destlen));
}
/* sets locale and elm_msg_cat */
static int locale_init_called = 0;
static int locale_error = 0;
void locale_init () {
#ifdef I_LOCALE
char *res;
#endif
DPRINT(Debug,9,(&Debug,
"locale_init: called = %d\n",
locale_init_called));
#ifdef I_LOCALE
if (setlocale(LC_ALL, "") == NULL) {
lib_error(FRM("Elm: Unsupported locale (check $LANG)\n"));
if (setlocale(LC_CTYPE,"") != NULL) {
lib_error(FRM("Elm: ... but succeed setting of LC_CTYPE\n"));
} else {
lib_error(FRM("Elm: ... check also $LC_CTYPE\n"));
}
locale_error = 1;
}
#endif
/* WARNING: Elm's version uses 0 as failure
* System uses (nl_catd) -1 as failure !
*/
elm_msg_cat = catopen("elm2.4me+", 0);
if (0 == elm_msg_cat ||
(nl_catd) -1 == elm_msg_cat) {
DPRINT(Debug,9,(&Debug,
"locale_init: catopen elm2.4me+ failed\n"));
}
/* NOTE: elm_msg_cat 'leaks' on end of program ... */
#ifdef I_LOCALE
res = setlocale(LC_CTYPE,NULL);
if (!res) {
lib_error(FRM("Elm: Unable to get current locale (LC_CTYPE)\n"));
locale_error = 1;
} else
strfcpy(display_locale,res, sizeof display_locale);
#endif
#ifdef HAVE_CODESET
res = nl_langinfo(CODESET);
if (!res) {
lib_error(FRM("Elm: Unable to get CODESET for current locale\n"));
locale_error = 1;
} else
strfcpy(display_codeset,res, sizeof display_codeset);
#endif
locale_init_called++;
}
enum matches { match_exact = 0,
match_codeset,
match_charset,
match_lang_country, match_lang, MATCH_COUNT };
struct charset_map_item * system_charset_map = NULL;
struct charset_map_item * user_charset_map = NULL;
static void map_system_charset P_((CONST char * lc_ctype, CONST char * codeset));
static void map_system_charset(lc_ctype, codeset)
CONST char * lc_ctype;
CONST char * codeset;
{
CONST char *lang = NULL;
CONST char *lang_country = NULL;
CONST char *charset = NULL;
charset_t d_matches[MATCH_COUNT];
int i,j;
char * default_system_charset = DEFAULT_SYSTEM_CHARSET;
char * c1;
char lbuf[3], cbuf[6];
if (!getenv("NOMETAMAIL") && (c1 = getenv("MM_CHARSET")) &&
c1[0]) {
default_system_charset = c1;
DPRINT(Debug,9,(&Debug,
"map_system_charset: using $MM_CHARSET (%s) as default system charset\n",
default_system_charset));
}
for (i = 0; i < MATCH_COUNT; i++)
d_matches[i] = NULL;
if (isascii(lc_ctype[0]) && isalpha(lc_ctype[0]) &&
isascii(lc_ctype[1]) && isalpha(lc_ctype[1]) &&
('.' == lc_ctype[2] || '_' == lc_ctype[2] || '\0' == lc_ctype[2])) {
strncpy(lbuf,lc_ctype,3);
lbuf[2] = '\0';
lang = lbuf;
if ('_' == lc_ctype[2]) {
if (isascii(lc_ctype[3]) && isalpha(lc_ctype[3]) &&
isascii(lc_ctype[4]) && isalpha(lc_ctype[4]) &&
('.' == lc_ctype[5] || '\0' == lc_ctype[5])) {
strncpy(cbuf,lc_ctype,6);
cbuf[5] = '\0';
lang_country = cbuf;
if ('.' == lc_ctype[5])
charset = lc_ctype+6;
}
} else if ('.' == lc_ctype[2])
charset = lc_ctype+3;
}
if (codeset[0]) {
DPRINT(Debug,10,(&Debug,
"map_system_charset: codeset: %s\n",
codeset));
d_matches[match_codeset] = codeset_name_to_charset(codeset);
if (!d_matches[match_codeset]) {
DPRINT(Debug,1,(&Debug,
"map_system_charset: codeset name %s unknown!\n",codeset));
}
}
if (lang) {
DPRINT(Debug,10,(&Debug,
"map_system_charset: %s -> lang: %s\n",
lc_ctype,lang));
}
if (lang_country) {
DPRINT(Debug,10,(&Debug,
"map_system_charset: %s -> lang_country: %s\n",
lc_ctype,lang_country));
}
if (charset) {
DPRINT(Debug,10,(&Debug,
"map_system_charset: %s -> charset: %s\n",
lc_ctype,charset));
}
for (i = 0; i < 3; i++) {
if ( i < 2) {
int k;
struct charset_map_item * F = user_charset_map;
if (1 == i)
F = system_charset_map;
if (!F)
continue;
for (k = 0; F[k].charset; k++) {
if (F[k].match) {
if (istrcmp (F[k].match, lc_ctype) == 0) {
d_matches[match_exact] = F[k].charset;
DPRINT(Debug,3,(&Debug,
"map_system_charset: user defined \"%s\" as %s\n",
lc_ctype,
d_matches[match_exact]->MIME_name ?
d_matches[match_exact]->MIME_name :
"<no MIME name>"));
}
if (charset && strncmp(F[k].match,"*.",2) == 0 &&
istrcmp (F[k].match+2, charset) == 0) {
d_matches[match_charset] = F[k].charset;
DPRINT(Debug,3,(&Debug,
"map_system_charset: user defined \"%s\" (*.%s) as %s\n",
lc_ctype, charset,
d_matches[match_charset]->MIME_name ?
d_matches[match_charset]->MIME_name :
"<no MIME name>"));
}
if (lang_country && istrcmp (F[k].match, lang_country) == 0) {
d_matches[match_lang_country] = F[k].charset;
DPRINT(Debug,3,(&Debug,
"map_system_charset: user defined \"%s\" (%s) as %s\n",
lc_ctype, lang_country,
d_matches[match_lang_country]->MIME_name ?
d_matches[match_lang_country]->MIME_name :
"<no MIME name>"));
}
if (lang_country && istrcmp (F[k].match, lang) == 0) {
d_matches[match_lang] = F[k].charset;
DPRINT(Debug,3,(&Debug,
"map_system_charset: user defined \"%s\" (%s) as %s\n",
lc_ctype, lang,
d_matches[match_lang]->MIME_name ?
d_matches[match_lang]->MIME_name :
"<no MIME name>"));
}
}
}
for (j = 0; j < MATCH_COUNT; j++)
if (d_matches[j]) {
system_charset = d_matches[j];
DPRINT(Debug,3,(&Debug,
"map_system_charset: using match %d: \"%s\" (codeset \"%s\") as %s\n",
j,lc_ctype,codeset,
system_charset->MIME_name ?
system_charset->MIME_name :
"<no MIME name>"));
return;
}
} else {
int val;
char buffer[STRING];
if (d_matches[match_codeset]) {
system_charset = d_matches[match_codeset];
DPRINT(Debug,3,(&Debug,
"map_display_charset: using match codeset: \"%s\" (codeset \"%s\") as %s\n",
lc_ctype,codeset,
system_charset->MIME_name ?
system_charset->MIME_name :
"<no MIME name>"));
return;
}
/* 1) ------ guess based on codeset ------------------------ */
if (codeset[0] &&
0 == strincmp(codeset,"ISO-8859-",9) &&
0 < (val = atoi(codeset+9))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else if (codeset[0] &&
0 == strincmp(codeset,"ISO_8859-",9) &&
0 < (val = atoi(codeset+9))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else if (codeset[0] &&
0 == strincmp(codeset,"ISO8859-",8) &&
0 < (val = atoi(codeset+8))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else if (codeset[0] &&
0 == strincmp(codeset,"ISO8859",7) &&
isascii(codeset[7]) && isdigit(codeset[7]) &&
'\0' == codeset[8]) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%c"),
codeset[7]);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
/* 2) ------ guess based on lc_ctype ------------------------ */
} else if (0 == strcmp(lc_ctype,"C"))
system_charset = MIME_name_to_charset("US-ASCII",
CHARSET_create);
else if (0 == istrcmp(lc_ctype,"ASCII") ||
0 == istrcmp(lc_ctype,"US-ASCII"))
system_charset = MIME_name_to_charset("US_ASCII",
CHARSET_create);
else if (0 == strincmp(lc_ctype,"ISO-8859-",9) &&
0 < (val = atoi(lc_ctype+9))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,CHARSET_create);
} else if (0 == strincmp(lc_ctype,"ISO_8859-",9) &&
0 < (val = atoi(lc_ctype+9))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,CHARSET_create);
} else if (0 == strincmp(lc_ctype,"ISO8859-",8) &&
0 < (val = atoi(lc_ctype+8))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,CHARSET_create);
/* 3) ------ guess based on charset part of locale ------------------------ */
} else if (charset && (0 == istrcmp(charset,"ASCII") ||
0 == istrcmp(charset,"US-ASCII")))
system_charset = MIME_name_to_charset("US-ASCII",
CHARSET_create);
else if (charset &&
0 == strincmp(charset,"ISO-8859-",9) &&
0 < (val = atoi(charset+9))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else if (charset &&
0 == strincmp(charset,"ISO_8859-",9) &&
0 < (val = atoi(charset+9))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else if (charset &&
0 == strincmp(charset,"ISO8859-",8) &&
0 < (val = atoi(charset+8))) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%d"),
val);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else if (charset &&
0 == strincmp(charset,"ISO8859",7) &&
isascii(charset[7]) && isdigit(charset[7]) &&
'\0' == charset[8]) {
elm_sfprintf(buffer, sizeof buffer,
FRM("ISO-8859-%c"),
charset[7]);
system_charset = MIME_name_to_charset(buffer,
CHARSET_create);
} else {
lib_error(FRM("Elm: Unable to map %.20s locale (LC_CTYPE) to MIME charset."),
lc_ctype);
if (codeset[0]) {
system_charset = MIME_name_to_charset(codeset,
CHARSET_create);
lib_error(FRM(" Codeset name %s was unknown. Treating %s as MIME name."),
codeset,codeset);
lib_error(FRM(" Check %.100s or %.100s"),
system_mime_charsets, user_mime_charsets);
} else {
system_charset = MIME_name_to_charset(default_system_charset,
CHARSET_create);
lib_error(FRM(" Using default (%.20s). Check %.100s or\n %.100s"),
default_system_charset,system_mime_charsets,
user_mime_charsets);
}
locale_error = 1;
}
DPRINT(Debug,3,(&Debug,
"map_display_charset: default \"%s\" as \"%s\"\n",
lc_ctype, system_charset->MIME_name));
}
}
}
/* shell value from passwd */
static char shell0[STRING] = "";
void user_init()
{
char *cp;
int r;
/** initialize the whole ball of wax.
**/
struct passwd *pass;
if (!locale_init_called)
locale_init ();
/* save original user and group ids */
userid = getuid();
groupid = getgid();
/* GNU library seems give _SC_SAVED_IDS as enumerated
value instead of #define so we can not test if
it is defined (as macro)
*/
#if defined(_SC_SAVED_IDS) || defined(_POSIX_VERSION)
r = sysconf(_SC_SAVED_IDS);
if (r < 0) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"sysconf(_SC_SAVED_IDS) failed: (errno=%d) %s\n",
err,error_description(err)));
have_saved_ids = 0;
} else {
have_saved_ids = r > 0;
DPRINT(Debug,1,(&Debug,
"*** have_saved_ids=%d\n",have_saved_ids));
}
#else
have_saved_ids = 0;
#endif
mailgroupid = getegid();
/* Get username (logname), home (login directory), and full_username
* (part of GCOS) field from the password entry for this user id.
* Full_username will get overridden by fullname in elmrc, if defined.
*
* For those sites that have various user names with the same user
* ID, use the passwd entry corresponding to the user name as long
* as it matches the user ID. Otherwise fall back on the entry
* associated with the user ID alone.
*/
if((cp = getenv("LOGNAME")) == NULL)
cp = getenv("USER");
if(cp != NULL && (pass = getpwnam(cp)) != NULL &&
pass->pw_uid == userid) {
; /* Null body */
} else if((pass = getpwuid(userid)) == NULL) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmYouHaveNoPasswordEntry,
"You have no password entry!"));
exit(1);
}
strfcpy(username, pass->pw_name, sizeof username);
if (pass->pw_dir)
strfcpy(home, pass->pw_dir, sizeof home);
else if (NULL != (cp = getenv("HOME")))
strfcpy(home,cp,sizeof home);
else
strfcpy(home,"/",sizeof home);
if (pass->pw_shell)
strfcpy(shell0, pass->pw_shell, sizeof shell0);
/* Null shell in /etc/passwd means /bin/sh */
if ('\0' == shell0[0])
strfcpy(shell0, "/bin/sh", sizeof shell0);
if((cp = get_full_name(username)) != NULL)
strfcpy(full_username, cp, sizeof full_username);
else
strfcpy(full_username, username, sizeof full_username);
/* fall back on logname */
elm_sfprintf(user_rc_file, sizeof user_rc_file,
FRM("%s/%s"), home, ELMRCFILE);
elm_sfprintf(user_text_file, sizeof user_text_file,
FRM("%s/%s"), home, USER_ALIAS_TEXT);
elm_sfprintf(user_data_file, sizeof user_data_file,
FRM("%s/%s"), home, USER_ALIAS_DATA);
elm_sfprintf(user_mime_types, sizeof user_mime_types,
FRM("%s/%s"), home, USER_MIME_TYPES);
elm_sfprintf(user_mailheaders, sizeof user_mailheaders,
FRM("%s/%s"), home, MAILHEADERS);
elm_sfprintf(user_mime_charsets, sizeof user_mime_charsets,
FRM("%s/%s"), home, USER_MIME_CHARSETS);
elm_sfprintf(user_iso2022_sets, sizeof user_iso2022_sets,
FRM("%s/%s"), home, USER_ISO2022_SETS);
elm_sfprintf(user_terminal_info, sizeof user_terminal_info,
FRM("%s/%s"), home, USER_TERMINAL_INFO);
elm_sfprintf(user_mail_services, sizeof user_mail_services,
FRM("%s/%s"), home, USER_MAIL_SERVICES);
#if DEBUG
/* Open debug files and print spooled debug output */
debug_user_init();
#endif
}
#ifdef I_NETDB
/* Seems that h_errno is macro on AIX */
#ifndef h_errno
extern int h_errno;
#endif
#endif
static int figure_domain P_((void));
static int figure_domain()
{
#ifdef I_NETDB
if (hostname[0]) {
struct hostent *he = gethostbyname(hostname);
if (!he) {
DPRINT(Debug,3,(&Debug,
"figure_domain: %s: h_errno=%d\n",
hostname,h_errno));
switch(h_errno) {
case TRY_AGAIN:
lib_error(CATGETS(elm_msg_cat, MeSet,MeTemporary,
"Address for %s is not yet found..."),
hostname);
}
} else {
int ok = 0;
int idx;
char *p;
if (NULL != (p =
strchr(he->h_name ,'.'))) {
if (!hostdomain[0])
strfcpy(hostdomain,p,sizeof hostdomain);
if (!hostfullname[0])
strfcpy(hostfullname, he->h_name, sizeof hostfullname);
ok = 1;
}
for (idx = 0; !ok && he->h_aliases[idx]; idx++)
if (NULL != (p =
strchr(he->h_aliases[idx],'.'))) {
if (!hostdomain[0])
strfcpy(hostdomain,p,sizeof hostdomain);
if (!hostfullname[0])
strfcpy(hostfullname, he->h_aliases[idx],
sizeof hostfullname);
ok = 1;
}
if (ok) {
DPRINT(Debug,3,(&Debug,
"hostname=\"%s\" -> hostdomain=\"%s\", hostfullname=\"%s\"\n",
hostname,hostdomain,hostfullname));
}
return ok;
}
}
#endif
return 0;
}
static void generate_hostfullname P_((void));
static void generate_hostfullname()
{
int hostlen, domlen;
/*
* now the tough part:
* we need to make three variables out of this stuff:
* hostname = just the hostname, as in bangpaths,
* this is whatever the user gave us so far,
* we wont change this one
* hostdomain = this is the domain considered local to this
* machine, and should be what we got above.
* hostfullname = this is the full FQDN of this machine,
* and is a strange combination of the first two.
* if tail(hostname) == hostdomain
* then hostfullname = hostname
* ie: node.ld.domain.type, ld.domain.type -> node.ld.domain.type
* else if hostname == hostdomain + 1
* then hostfullname = hostname
* ie: domain.type, .domain.type -> domain.type
*
* else hostfullname = hostname + hostdomain
* ie: host, .domain.type -> host.domain.type
* lost yet?
*/
DPRINT(Debug,3,(&Debug,
"hostname=\"%s\",hostdomain=\"%s\" ",
hostname,hostfullname));
hostlen = strlen(hostname);
domlen = strlen(hostdomain);
if (hostlen >= domlen) {
if (istrcmp(&hostname[hostlen - domlen], hostdomain) == 0)
strfcpy(hostfullname, hostname, sizeof hostfullname);
else {
strfcpy(hostfullname, hostname, sizeof hostfullname);
strfcat(hostfullname, hostdomain, sizeof hostfullname);
}
} else {
if (istrcmp(hostname, hostdomain + 1) == 0)
strfcpy(hostfullname, hostname, sizeof hostfullname);
else {
strfcpy(hostfullname, hostname, sizeof hostfullname);
strfcat(hostfullname, hostdomain, sizeof hostfullname);
}
}
DPRINT(Debug,3,(&Debug,
"-> hostfullname=\"%s\"\n",
hostfullname));
}
static int init_defaults_called = 0;
static init_default_hook **hooklist = NULL;
static int hooklist_len = 0;
void add_init_default_hook(hook)
init_default_hook *hook;
{
if (init_defaults_called) {
hook(&errors);
}
hooklist = safe_realloc(hooklist,(hooklist_len+1) * sizeof(hooklist[0]));
hooklist[hooklist_len] = hook;
hooklist_len++;
}
int init_defaults() {
char *cp;
FILE * file;
#ifdef DOUNAME
struct utsname u_name;
#endif
int i;
/* Establish some defaults in case elmrc is incomplete or not there.
* Defaults for other elmrc options were established in their
* declaration - in elm.h. And defaults for sent_mail and recvd_mail
* are established after the elmrc is read in since these default
* are based on the folders directory name, which may be given
* in the emrc.
*/
if (init_defaults_called) {
DPRINT(Debug,1,(&Debug,"init_defaults called twice!!\n"));
}
init_defaults_called = 1;
errors = 0;
/*
* Get the host name as per configured behavior.
*/
#ifdef GETHOSTNAME
if (-1 == gethostname(hostname, sizeof(hostname))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"gethostname failed: (errno=%d) %s\n",
err,error_description(err)));
} else {
DPRINT(Debug,3,(&Debug,
"gethostname: Setting hostname to %s\n",
hostname));
}
#endif
#ifdef DOUNAME
if (-1 == uname(&u_name)) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"uname failed: (errno=%d) %s\n",
err,error_description(err)));
} else if (!hostname[0]) {
strfcpy(hostname, u_name.nodename, sizeof hostname);
DPRINT(Debug,3,(&Debug,
"uname: Setting hostname to %s\n",
hostname));
}
#endif
if (!hostname[0]) {
DPRINT(Debug,1,(&Debug,
"Default host name is not available\n"));
}
/*
* now get the domain name, used to build the full name
*/
if (!figure_domain()) {
if (gethostdomain(hostdomain, sizeof(hostdomain)) <0) {
DPRINT(Debug,1,(&Debug,
"Default domain name is not available\n"));
hostdomain[0] = '\0';
} else if (hostname[0] && hostdomain[0]) {
generate_hostfullname();
}
}
/* Determine the default mail file name.
*
* First look for an environment variable MAIL, then
* use then mailhome if it is not found
*/
{
char *X = elm_message(FRM("%s%s"), mailhome, username);
set_dt_estr(&defaultfile_e,X,"MAIL");
free(X);
}
allowed_precedences[0] = '\0';
/* no defaults for those */
set_dt_estr(&shell_e,shell0,"SHELL");
/* Shell is set from /etc/passwd in user_init () */
#ifdef USE_BUILTIN_PAGER
set_dt_estr(&pager_e, "builtin++", NULL);
#else
set_dt_estr(&pager_e,default_pager,"PAGER");
#endif
set_dt_estr(&temp_dir_e,default_temp,"TMPDIR");
set_dt_estr(&editor_e,default_editor,"EDITOR");
if ((cp = getenv("MAILCAPS")) == NULL) {
/* RFC 1524:
For UNIX, a path search of mailcap files is specified. The default
path search is specified as including at least the following:
$HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap
*/
char *X[] = { "/etc/mailcap", "/usr/etc/mailcap",
"/usr/local/etc/mailcap", NULL };
char *G = elm_message(FRM("%s/.mailcap"),home);
char **X1;
/* Fake recursive call -- expand_dt_path ignores non-existiant
entries.
*/
DPRINT(Debug,9,(&Debug,
"Adding default entry to metamail-mailcaps: %s\n",
G));
expand_dt_path(&metamail_mailcaps,"metamail-mailcaps",
G,2);
for (X1 = X; *X1; X1++) {
DPRINT(Debug,9,(&Debug,
"Adding default entry to metamail-mailcap: %s\n",
*X1));
expand_dt_path(&metamail_mailcaps,"metamail-mailcaps",
*X1,2);
}
DPRINT(Debug,9,(&Debug,
"Adding default entry to internal-mailcaps: %s\n",
G));
expand_dt_path(&internal_mailcaps,"internal-mailcaps",
G,2);
for (X1 = X; *X1; X1++) {
DPRINT(Debug,9,(&Debug,
"Adding default entry to internal-mailcap: %s\n",
*X1));
expand_dt_path(&internal_mailcaps,"internal-mailcaps",
*X1,2);
}
free(G);
} else {
DPRINT(Debug,9,(&Debug,
"Adding unexpanded entry to metamail-mailcaps: $MAILCAPS\n"
));
metamail_mailcaps.unexpanded = safe_strdup("$MAILCAPS");
DPRINT(Debug,9,(&Debug,
"Adding unexpanded entry to internal-mailcaps: $MAILCAPS\n"
));
internal_mailcaps.unexpanded = safe_strdup("$MAILCAPS");
}
folders_e.unexpanded = elm_message(FRM("~/%s"), default_folders);
map_txtdir_e.unexpanded = safe_strdup("{lib}/elm.map.txt");
map_bindir_e.unexpanded = safe_strdup("{lib}/elm.map.bin");
readmsg_e.unexpanded = safe_strdup("{bin}/readmsg");
calendar_file_e.unexpanded =
elm_message(FRM("~/%s"), dflt_calendar_file);
dead_letter_dir_e.unexpanded = safe_strdup("~/Canceled.mail.dir");
strfcpy(e_editor, emacs_editor, sizeof e_editor);
strfcpy(v_editor, default_editor, sizeof v_editor);
#ifdef USE_PGP
set_dt_estr(&gpg_path_e,GPG_PATH,NULL);
set_dt_estr(&pgp2_path_e,PGP2_PATH,NULL);
set_dt_estr(&pgp5_dir_e,PGP5_DIR,NULL);
#endif
set_dt_estr(&metamail_path_e,METAMAIL_PATH,NULL);
set_dt_estr(&printout_e,DEFAULT_PRINTOUT,NULL);
/* try system-wide rc file */
file = fopen(system_rc_file, "r");
if ( file != NULL ) {
do_rc(file, SYSTEM_RC,system_rc_file);
fclose(file);
} else if (!hostname[0] || !hostdomain[0] || !hostfullname[0]) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmFailedSystemRC,
"Failed to open RC file %s: %s"),
system_rc_file,error_description(err));
errors++;
}
if (figure_domain()) {
/* Do nothing */
} else if (!hostname[0] || !hostdomain[0]) {
if (hostfullname[0]) {
char * p = strchr(hostfullname,'.');
if (!hostname[0])
strfcpy(hostname,hostfullname,sizeof hostname);
if (!hostdomain[0]) {
if (p)
strfcpy(hostdomain,p,sizeof hostdomain);
else
strfcpy(hostdomain,".localdomain",sizeof hostdomain);
}
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmDefineHostname,
"Give \"hostname\", \"hostfullname\" and \"hostdomain\" on RC file: %s"),
system_rc_file);
if (!hostname[0])
strfcpy(hostname,"localhost",sizeof hostname);
if (!hostdomain[0])
strfcpy(hostdomain,".localdomain",sizeof hostdomain);
if (!hostfullname[0])
strfcpy(hostfullname,hostname,sizeof hostfullname);
errors++;
}
} else if (!hostfullname[0]) {
if ('.' != hostdomain[0]) {
char buffer[SLEN];
strfcpy(buffer,hostdomain,sizeof buffer);
strfcpy(hostdomain,".",sizeof hostdomain);
strfcat(hostdomain,buffer,sizeof hostdomain);
DPRINT(Debug,3,(&Debug,
"hostdomain=\"%s\" -> hostdomain=\"%s\"\n",
buffer,hostdomain));
}
generate_hostfullname();
}
/* Also bindata ... notice temorary variable */
expand_map_bin("bindata", bindata_path_global, raw_bindata_path,
sizeof(bindata_path));
parse_iso2022_map(system_iso2022_sets,&errors,ml_system);
system_charset_map = load_charset_map(system_mime_charsets,&errors);
#ifdef REMOTE_MBX
parse_service_entries(system_mail_services,1 /* SYSTEM */,&errors);
#endif
for (i = 0; i < hooklist_len; i++) {
hooklist[i](&errors);
}
DPRINT(Debug,3,(&Debug,
"init_defaults=%d (errors)\n",errors));
return errors;
}
enum charset_keyword { cskw_none = 0, cskw_SYSTEM, cskw_DISPLAY, cskw_TEXT };
static enum charset_keyword special_charset_keyword P_((const char *value));
static enum charset_keyword special_charset_keyword(value)
CONST char *value;
{
if (0 == strcmp(value,"SYSTEM"))
return cskw_SYSTEM;
else if (0 == strcmp(value,"DISPLAY"))
return cskw_DISPLAY;
else if (0 == strcmp(value,"TEXT"))
return cskw_TEXT;
else
return cskw_none;
}
void post_process_charset_options()
{
switch (special_charset_keyword(raw_text_charset)) {
case cskw_SYSTEM: text_charset = system_charset; break;
case cskw_DISPLAY: text_charset = display_charset; break;
case cskw_TEXT:
text_charset = display_charset;
strfcpy(raw_text_charset,"DISPLAY",sizeof raw_text_charset);
break;
}
switch (special_charset_keyword(raw_display_charset)) {
case cskw_SYSTEM: wanted_display_charset = system_charset; break;
case cskw_DISPLAY: wanted_display_charset = display_charset; break;
case cskw_TEXT: wanted_display_charset = text_charset; break;
}
if (!wanted_display_charset ||
0 == (charset_properties(wanted_display_charset) & CS_mapping)) {
if (0 != charset_properties(system_charset))
wanted_display_charset = system_charset;
else
wanted_display_charset = ASCII_SET;
DPRINT(Debug,2,(&Debug,
"Setting (wanted) display-charset to %s instead.\n",
wanted_display_charset->MIME_name ?
wanted_display_charset->MIME_name :
"<no MIME name>"));
}
if (!text_charset || !text_charset->MIME_name) {
text_charset = ASCII_SET;
DPRINT(Debug,2,(&Debug,
"Setting text-charset to %s instead.\n",
text_charset->MIME_name ?
text_charset->MIME_name :
"<no MIME name"));
}
switch (special_charset_keyword(raw_local_fs_charset)) {
case cskw_SYSTEM: local_fs_charset = system_charset; break;
case cskw_DISPLAY: local_fs_charset = display_charset; break;
case cskw_TEXT: local_fs_charset = text_charset; break;
}
switch (special_charset_keyword(raw_default_nomime_charset)) {
case cskw_SYSTEM: default_nomime_charset = system_charset; break;
case cskw_DISPLAY: default_nomime_charset = display_charset; break;
case cskw_TEXT: default_nomime_charset = text_charset; break;
}
switch (special_charset_keyword(raw_default_mimetext_charset)) {
case cskw_SYSTEM: default_mimetext_charset = system_charset; break;
case cskw_DISPLAY: default_mimetext_charset = display_charset; break;
case cskw_TEXT: default_mimetext_charset = text_charset; break;
}
#ifdef REMOTE_MBX
switch (special_charset_keyword(raw_imap_charset)) {
case cskw_SYSTEM: imap_charset = system_charset; break;
case cskw_DISPLAY: imap_charset = display_charset; break;
case cskw_TEXT: imap_charset = text_charset; break;
}
#endif
}
static init_default_hook **hooklist_rc = NULL;
static int hooklist_rc_len = 0;
static int read_rc_file_called = 0;
void add_read_rc_file_hook(hook)
init_default_hook *hook;
{
if (read_rc_file_called) {
hook(&errors);
}
hooklist_rc = safe_realloc(hooklist_rc,
(hooklist_rc_len+1) * sizeof(hooklist_rc[0]));
hooklist_rc[hooklist_rc_len] = hook;
hooklist_rc_len++;
}
int read_rc_file(flag)
int flag;
{
/** this routine does all the actual work of reading in the
.rc file... **/
int err;
int i;
errors = 0;
if (read_rc_file_called) {
DPRINT(Debug,1,(&Debug,"read_rc_file called twice!\n"));
}
read_rc_file_called = 1;
/* Look for the elmrc file */
err = can_open(user_rc_file, "r");
if (err) {
DPRINT(Debug,2,(&Debug,
"Warning:User has no \"%s\" file (can_open)\n\n",
user_rc_file));
} else {
FILE *file = NULL;
if ((file = fopen(user_rc_file, "r")) == NULL) {
DPRINT(Debug,2,(&Debug,
"Warning:Open \"%s\" failed\n\n",
user_rc_file));
}
if (file != NULL) {
do_rc(file, LOCAL_RC, ELMRCFILE);
fclose(file);
}
}
/* Also bindata ... */
expand_map_bin("bindata", bindata_path, raw_bindata_path,
sizeof(bindata_path));
parse_iso2022_map(user_iso2022_sets,&errors, ml_user);
user_charset_map = load_charset_map(user_mime_charsets,&errors);
#ifdef REMOTE_MBX
parse_service_entries(user_mail_services,0 /* USER */,&errors);
#endif
for (i = 0; i < hooklist_rc_len; i++) {
hooklist_rc[i](&errors);
}
post_init_check(flag);
DPRINT(Debug,3,(&Debug,
"read_rc_file=%d (errors)\n",errors));
return errors;
}
void post_init_check(flag)
int flag;
{
struct stat st_buffer;
char *t, *t1;
t = give_dt_estr_as_str(&folders_e,"maildir");
t1 = give_dt_estr_as_str(&extra_mailbox_dir_e,
"extra-mailbox-dir");
if (t1 && t && 0 == strcmp(t1,t)) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmExtraNoFolders,
"\"extra-mailbox-dir\" should not be \"folders\" or \"maildir\" directory."));
free(extra_mailbox_dir_e.unexpanded);
extra_mailbox_dir_e.unexpanded = NULL;
mark_local_changed(& extra_mailbox_dir_e);
}
t = give_dt_estr_as_str(&dead_letter_dir_e,"dead-letter-dir");
/* dead-letter-dir is create automatically, if it does not exists */
if (t &&
0 == stat(t,&st_buffer) &&
#ifdef S_ISDIR
!S_ISDIR(st_buffer.st_mode)
#else
S_IFDIR != (st_buffer.st_mode & S_IFMT)
#endif
) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadDeadLetterDir,
"\"dead-letter-dir\" should be directory."));
free(dead_letter_dir_e.unexpanded);
dead_letter_dir_e.unexpanded = NULL;
mark_local_changed(& dead_letter_dir_e);
}
if (! attachment_dir_e.unexpanded) {
char * tmp = elm_message(FRM("%s/Documents"),home);
if (0 == access(tmp,ACCESS_EXISTS)) {
attachment_dir_e.expanded = tmp;
attachment_dir_e.unexpanded = safe_strdup("~/Documents");
} else
free(tmp);
}
allow_forms = (allow_forms?MAYBE:NO);
if ((elm_timeout != 0) && (elm_timeout < 10)) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTimeoutLTTen,
"Warning: timeout is set to less than 10 seconds. Ignored."));
elm_timeout = 0;
}
if (readdatapercentinc < 1) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmReadDataIncrement,
"Warning: readdatapercentinc is set to less than 1. Ignored."));
readdatapercentinc = 1;
mark_local_changed(& readdatapercentinc);
}
if (readmsginc < 1) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmReadMessageIncrement,
"Warning: readmsginc is set to less than 1. Ignored."));
readmsginc = 1;
mark_local_changed(& readmsginc);
}
if (sleepmsg < 0) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmSleepMessageInvalid,
"Warning: sleepmsg is set to less than 0. Setting to 0."));
sleepmsg = 0;
mark_local_changed(& sleepmsg);
}
#ifdef BACKGROUD_PROCESSES
if (background_wait_time < 0) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBackgroundLLT,
"Warning: background_wait_time is set less than 0. Setting to 0."));
background_wait_time = 0;
mark_local_changed(& background_wait_time);
}
#endif
/* If recvd_mail or sent_mail havent't yet been established in
* the elmrc, establish them from their defaults.
* Then if they begin with a metacharacter, replace it with the
* folders directory name.
*/
if(!recvd_mail_e.unexpanded) {
recvd_mail_e.unexpanded = safe_strdup(default_recvdmail);
}
if(!sent_mail_e.unexpanded) {
sent_mail_e.unexpanded = safe_strdup(default_sentmail);
}
if (-1 == auto_copy_sent) {
if (dt_estr_is_disabled(&sent_mail_e)) {
DPRINT(Debug,5,(&Debug,"'copy' defaults to OFF (sentmail is disabled)\n"));
auto_copy_sent = 0;
} else {
DPRINT(Debug,5,(&Debug,"'copy' defaults to ON\n"));
auto_copy_sent = 1;
}
}
expand_map_bin("unidata", unidata_path, raw_unidata_path,
sizeof(unidata_path));
expand_map_bin("bindata", bindata_path, raw_bindata_path,
sizeof(bindata_path));
map_system_charset(display_locale,display_codeset);
#if defined(WCHAR) && defined(__STDC_ISO_10646__)
change_system_charset();
#endif
/* Current display charset is locale charset */
display_charset = system_charset;
if (!special_charset_keyword(raw_text_charset)) {
if (! load_charset_map_info(&text_charset,
raw_text_charset) ) {
char buffer[LONG_STRING];
do_expand_env("text-charset", buffer,
raw_text_charset,
sizeof(buffer));
text_charset = MIME_name_to_charset(buffer,CHARSET_create);
}
if (!(CS_mapping & charset_properties(text_charset))) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmUnknownTextCharset,
"text-charset %s is unknown, conversion to text-charset does not work"),
text_charset->MIME_name ?
text_charset->MIME_name :
raw_text_charset);
strfcpy(raw_text_charset,"DISPLAY",sizeof raw_text_charset);
text_charset = display_charset;
mark_local_changed(& raw_text_charset);
}
}
if (!special_charset_keyword(raw_display_charset)) {
if (! load_charset_map_info(& wanted_display_charset,
raw_display_charset )) {
char buffer[LONG_STRING];
do_expand_env("display-charset", buffer,
raw_display_charset,
sizeof(buffer));
wanted_display_charset = MIME_name_to_charset(buffer,CHARSET_create);
}
if (!(CS_mapping & charset_properties(wanted_display_charset))) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnknownDisplayCharset,
"display-charset %s is unsupported, charset switching does not work"),
wanted_display_charset->MIME_name ?
wanted_display_charset->MIME_name :
raw_display_charset);
strfcpy(raw_display_charset,"SYSTEM",
sizeof raw_display_charset);
wanted_display_charset = system_charset;
mark_local_changed(& raw_display_charset);
}
}
if (!special_charset_keyword(raw_local_fs_charset)) {
if (! load_charset_map_info(&local_fs_charset,
raw_local_fs_charset) ) {
char buffer[LONG_STRING];
do_expand_env("local-fs-charset", buffer,
raw_local_fs_charset,
sizeof(buffer));
local_fs_charset = MIME_name_to_charset(buffer,CHARSET_create);
}
if (!(CS_mapping & charset_properties(local_fs_charset))) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnknownFSCharset,
"local-fs-charset %s is unsupported, file access does not work"),
local_fs_charset->MIME_name ?
local_fs_charset->MIME_name :
raw_local_fs_charset);
strfcpy(raw_local_fs_charset,"SYSTEM",
sizeof raw_local_fs_charset);
local_fs_charset = system_charset;
mark_local_changed(& raw_local_fs_charset);
}
}
if (!special_charset_keyword(raw_default_nomime_charset)) {
if (! load_charset_map_info(& default_nomime_charset,
raw_default_nomime_charset) ) {
char buffer[LONG_STRING];
do_expand_env("default-nomime-charset", buffer,
raw_default_nomime_charset,
sizeof(buffer));
default_nomime_charset = MIME_name_to_charset(buffer,CHARSET_create);
}
if (!(CS_mapping & charset_properties(default_nomime_charset))) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnknownDef1Charset,
"default-nomime-charset %s is unsupported"),
default_nomime_charset->MIME_name ?
default_nomime_charset->MIME_name :
raw_default_nomime_charset);
strfcpy(raw_default_nomime_charset,"SYSTEM",
sizeof raw_default_nomime_charset);
default_nomime_charset = system_charset;
mark_local_changed(& raw_default_nomime_charset);
}
}
if (!special_charset_keyword(raw_default_mimetext_charset)) {
if (! load_charset_map_info(& default_mimetext_charset,
raw_default_mimetext_charset) ) {
char buffer[LONG_STRING];
do_expand_env("default-mime-text-charset", buffer,
raw_default_mimetext_charset,
sizeof(buffer));
default_mimetext_charset = MIME_name_to_charset(buffer,CHARSET_create);
}
if (!(CS_mapping & charset_properties(default_mimetext_charset))) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnknownDef2Charset,
"default-mime-text-charset %s is unsupported"),
default_mimetext_charset->MIME_name ?
default_mimetext_charset->MIME_name :
raw_default_mimetext_charset);
strfcpy(raw_default_mimetext_charset,"US-ASCII",
sizeof raw_default_mimetext_charset);
default_mimetext_charset = ASCII_SET;
mark_local_changed(& raw_default_mimetext_charset);
}
}
#ifdef REMOTE_MBX
if (!special_charset_keyword(raw_imap_charset)) {
if (! load_charset_map_info(& imap_charset,
raw_imap_charset) ) {
char buffer[LONG_STRING];
do_expand_env("imap-charset", buffer,
raw_imap_charset,
sizeof(buffer));
imap_charset = MIME_name_to_charset(buffer,CHARSET_create);
}
if (!(CS_mapping & charset_properties(imap_charset))) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnknownIMAPCharset,
"imap-charset %s is unsupported"),
imap_charset->MIME_name ?
imap_charset->MIME_name :
raw_imap_charset);
strfcpy(raw_imap_charset,"SYSTEM",
sizeof raw_imap_charset);
imap_charset = system_charset;
mark_local_changed(& raw_imap_charset);
}
}
#endif
post_process_charset_options();
if (!(CS_mapping & charset_properties(system_charset))) {
/* Don't increment errors variable because this comes
* from locale (via mime.charsets) and not from elmrc
*/
if (system_charset->MIME_name)
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnsupportedLocale,
"WARNING: Locale %s (charset %s) is unsupported, will cause problems!"),
display_locale,system_charset->MIME_name);
else
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmUnsupportedLocale2,
"WARNING: Locale %s is unsupported, will cause problems!"),
display_locale);
locale_error = 1;
}
if (locale_error == 1) {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmLocaleProblem,
"Problem with locale (system character set)! Elm ME+ will behave erratically."));
/* Long wait that message will be noticed ... */
#if POLL_METHOD
wait_for_timeout(10);
#else
sleep(10);
#endif
locale_error++;
}
if (
(
(wanted_display_charset != system_charset &&
0 != (CS_mapping & charset_properties(wanted_display_charset)) &&
(!wanted_display_charset->MIME_name ||
0 != istrcmp(wanted_display_charset->MIME_name,"US-ASCII"))
#ifndef ASCII_CTYPE
&& (!wanted_display_charset->MIME_name ||
0 != istrcmp(wanted_display_charset->MIME_name,"ISO-8859-1"))
#endif
)
|| allow_charset_switching
) &&
0 != strcmp(unidata_path,"none")) {
/* We are going to need unidata information --
therefore check availivility ! */
if (0 == (flag & READ_FLAG_UNIDATA_INIT)
&&
!default_unidata()) {
lib_error(CATGETS(elm_msg_cat, ElmSet,ElmNoUnicodeData,
"No Unicode data available: unidata: %s"),
raw_unidata_path);
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet,ElmUnidataSetting,
"Setting unidata=none, displaycharset=SYSTEM, allow-charset-switching=OFF"));
strfcpy(raw_unidata_path,"none",sizeof raw_unidata_path);
strfcpy(unidata_path,"none",sizeof unidata_path);
strfcpy(raw_display_charset,"SYSTEM",
sizeof raw_display_charset);
wanted_display_charset = system_charset;
allow_charset_switching = 0;
mark_local_changed(& raw_unidata_path);
mark_local_changed(& raw_display_charset);
mark_local_changed(& allow_charset_switching);
}
}
if (0 != strcmp(bindata_path,"none") &&
0 != strcmp(bindata_path_global,bindata_path)) {
if (0 == (flag & READ_FLAG_BINDATA_INIT)
&&
!default_bindata()) {
lib_error(CATGETS(elm_msg_cat, ElmSet,ElmBinaryMapData,
"No binary map data available: bindata: %s"),
raw_bindata_path);
errors++;
strfcpy(raw_bindata_path,"none",sizeof raw_bindata_path);
strfcpy(bindata_path,"none",sizeof bindata_path);
mark_local_changed(& raw_bindata_path);
}
}
#ifdef USE_PGP
if (pgp_none == give_dt_enumerate_as_int(&send_pgp_version)) {
char * gpg_path_val = give_dt_estr_as_str(&gpg_path_e, "gpg");
char * pgp2_path_val = give_dt_estr_as_str(&pgp2_path_e, "pgp2");
char * pgp5_dir_val = give_dt_estr_as_str(&pgp5_dir_e, "pgp5-dir");
if (gpg_path_val && '/' == gpg_path_val[0])
send_pgp_version.val = gpg;
if (pgp5_dir_val && '/' == pgp5_dir_val[0])
send_pgp_version.val = pgp5;
if (pgp2_path_val && '/' == pgp2_path_val[0])
send_pgp_version.val = pgp2;
}
#endif
#ifdef USE_DLOPEN
post_init_shared_options(&errors);
#endif
}
/* Return rest */
static char * split_keyword(buffer,line_len,keyword,size,tag,
assig)
char *buffer;
int line_len;
char *keyword;
int size;
char **tag;
int *assig;
{
int i;
char * c;
DPRINT(Debug,10,(&Debug,
"split_keyword len=%d, buffer=%s\n",
line_len,buffer));
*assig = 0;
i = 0;
for (c = buffer; c - buffer < line_len && i < size; c++) {
if ('_' == *c)
keyword[i++] = '-';
else if (!*tag && ':' == *c) {
/* Mark tag from buffer */
*c = '\0';
*tag = buffer;
i = 0;
} else if (!isascii(*c))
break;
else if (!ok_rc_char(*c))
break;
else {
keyword[i++] = tolower((unsigned char)*c);
}
}
keyword[i] = '\0';
while (whitespace(*c))
c++;
if ('=' == *c) {
c++;
*assig = 1;
}
while (whitespace(*c))
c++;
DPRINT(Debug,10,(&Debug,
"split_keyword: keyword(i=%d)=%s\n",
i,keyword));
if (*tag) {
DPRINT(Debug,10,(&Debug,
"split_keyword: tag=%s\n",*tag));
}
DPRINT(Debug,10,(&Debug,
"split_keyword=%s\n",c));
return c;
}
static void do_rc(file, lcl, filename)
FILE *file;
enum record_mode lcl;
char *filename;
{
struct rc_save_info_rec * prev_type = NULL;
struct hist_record * rec = NULL;
char current_tag[SLEN];
int ignored = 0;
char * buffer = NULL;
int r; /* length of line or error/eof status */
if (!file)
return;
lineno=0;
current_tag[0] = '\0';
while (0 <= ( r = malloc_gets(&buffer,MAX_LINE,file))) {
char * tag = NULL;
char keyword[SLEN], *c;
char * rest = NULL;
int negate = 0;
int assig = 0;
int i;
lineno++;
if (!buffer) /* EOF */
break;
if (buffer[0] == '#' /* comment */
|| r < 1) /* empty line */
continue;
rest = split_keyword(buffer,r,keyword, sizeof keyword,&tag,
&assig);
if (tag && !keyword[0]) {
strfcpy(current_tag, tag, sizeof current_tag);
if (rest[0] && '#' != rest[0]) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmIgnoredLine,
"Rest of line ignored after \"%s:\" on line %d on file %s"),
tag, lineno,filename);
errors++;
}
} else if (!keyword[0]) {
if (prev_type != NULL) {
if (RCTYPE_magic != prev_type->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"do_rc",
"Bad prev_type",0);
if (rec) {
rec->old_line = safe_realloc(rec->old_line,
sizeof(rec->old_line[0]) *
( rec->line_count + 1));
rec->old_line [ rec->line_count ] = safe_strdup(rest);
rec->line_count++;
}
if (!prev_type->dt_type ->
parse_cline(prev_type,
lcl,
rest,
lineno,
filename)) {
errors++;
/* If there was errors, then assume that rewriting
of elmrc entry causes it to be rewritten
*/
if (rec)
rec->changed++;
}
}
} else if (assig) {
if (tag || current_tag[0]) {
struct rc_save_info_rec * rc_options = NULL;
int rc_option_count = 0;
if (!tag)
tag = current_tag;
else
ignored = 0;
#ifdef USE_DLOPEN
if (give_options(tag,&rc_options,&rc_option_count)) {
prev_type = locate_option(rc_options,rc_option_count,
keyword,rest,filename,
&negate);
ignored = 0;
if (!prev_type) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadKeyTagInElmrc,
"I can't understand keyword \"%s\" (section %s) in line %d in \"%s\" file"),
keyword, tag,lineno,filename);
continue;
}
} else if (!ignored) {
ignored = 1;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmIgnoredSection,
"Keywords on section \"%s\" ignored starting from line %d on file %s"),
tag, lineno,filename);
}
#else
if (!ignored) {
ignored = 1;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmSharedIgnoredSection,
"Shared libraries not supported. Section \"%s\" ignored starting from line %d on file %s"),
tag, lineno,filename);
errors++;
}
#endif
} else {
prev_type = locate_option(save_info,NUMBER_OF_SAVEABLE_OPTIONS,
keyword,rest,filename,&negate);
if (!prev_type) {
errors++;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadKeyInElmrc,
"I can't understand keyword \"%s\" in line %d in \"%s\" file"),
keyword, lineno,filename);
continue;
}
}
if (!prev_type)
continue;
rec = need_record(lcl,prev_type,tag);
if (rec) {
if (rec->line_count)
panic("RC PANIC",__FILE__,__LINE__,"do_rc",
"Bad prev_type",0);
rec->old_line = safe_malloc(sizeof(rec->old_line[0]));
rec->old_line[0] = safe_strdup(rest);
rec->line_count = 1;
}
if (ignored)
continue;
if (prev_type->flags & FL_SYS && lcl == LOCAL_RC) {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmBadLocalKeyInElmrc,
"Keyword \"%s\" is not valid on user file %s"),
prev_type->name,filename);
continue;
}
if (!rc_eval_tail(prev_type,lcl,rest,lineno,filename,negate)) {
errors++;
/* If there was errors, then assume that rewriting
of elmrc entry causes it to be rewritten
*/
if (rec)
rec->changed++;
}
} else {
prev_type = NULL;
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadLineInElmrc,
"Keyword \"%s\" without = -character in line %d in \"%s\" file"),
keyword, lineno,filename);
errors++;
}
}
if (-1 == r) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTooLongLine,
"%.30s: %d: Too long line: %.30s..."),
filename,lineno+1,
buffer ? buffer : "<not available>");
errors++;
}
if (ferror(file)) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorReading,
"Error reading from %.50s"),
filename);
errors++;
}
if (buffer)
free(buffer);
}
/*
* set the named parameter according to save_info structure.
* This routine may call itself (DT_SYN or DT_MLT).
* Also tags params that were set in "local" (personal) RC file
* so we know to save them back out in "o)ptions" screen.
* Uses an internal table to decode sort-by params...should be coupled
* with sort_name(), etc...but...
*/
/* read_rc.c. -- return NULL on failure
otherwise pointer to option
*/
static struct rc_save_info_rec *locate_option(rc_options,rc_option_count,
word1,word2,filename,negate)
struct rc_save_info_rec * rc_options;
int rc_option_count;
char *word1;
char *word2;
char *filename;
int *negate;
{
int x, y = 0;
if ('!' == *word1) {
(*negate)++;
word1++;
}
for (x=0; x < rc_option_count; ++x) {
y = strcmp(word1, rc_options[x].name);
if (y <= 0)
break;
}
if (y != 0)
return NULL;
return & (rc_options[x]);
}
int rc_eval_tail(ret,lcl,value,lineno,filename,negate)
struct rc_save_info_rec *ret;
int lcl;
char *value;
int lineno;
char *filename;
int negate;
{
if (lcl == LOCAL_RC)
ret->flags |= FL_LOCAL;
ret->flags |= FL_CHANGED;
if (RCTYPE_magic != ret->dt_type->magic)
panic("RC PANIC",__FILE__,__LINE__,"rc_eval_tail",
"Bad config item type",0);
if (! ret->dt_type->parse_line(ret,
lcl,
value,
lineno,
filename,
negate))
return 0;
return 1;
}
struct rc_save_info_rec * do_set(lcl, word1, word2, filename)
int lcl;
char *word1, *word2;
char *filename;
{
int negate = 0;
struct rc_save_info_rec * ret = locate_option(save_info,
NUMBER_OF_SAVEABLE_OPTIONS,
word1,word2,filename,
&negate);
if (!ret) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadKeyInElmrc,
"I can't understand keyword \"%s\" in line %d in \"%s\" file"),
word1, lineno,filename);
return NULL;
}
if (!rc_eval_tail(ret,lcl,word2,lineno,filename,negate))
return NULL;
return ret;
}
static CONST char WEED_NO_DEFAULT[] = "*clear-weed-list*";
int matches_weedlist(buffer)
char *buffer;
{
/** returns true iff the first 'n' characters of 'buffer'
match an entry of the weedlist **/
int i;
static char *default_list[] =
{ ">From", "In-Reply-To:",
"References:", "Newsgroups:", "Received:",
"Apparently-To:", "Message-Id:", "Content-Type:",
"Content-Length:", "MIME-Version:",
"Content-Transfer-Encoding:",
"From", "X-Mailer:", "Status:",
"X-ELM-",
"X-UIDL", /* Generated by some POP deamons */
"Return-Path:",
"List-ID:",
"List-Help:", "List-Subscribe:", "List-Unsubscribe:",
"List-Post:", "List-Owner:", "List-Archive:",
"*end-of-defaults*", NULL
};
char **list = give_dt_path_as_elems(&weedlist,"weedout");
/* If fist elem is "*clear-weed-list*" then default list is not
used
*/
if (!list || !list[0] ||
0 != strcmp(list[0],WEED_NO_DEFAULT)) {
for (i = 0; default_list[i]; i++) {
if (strincmp(buffer, default_list[i], strlen(default_list[i])) == 0)
return(1);
}
}
if (list) {
for (i=0;list[i]; i++) {
if (strincmp(buffer, list[i], strlen(list[i])) == 0)
return(1);
}
}
return(0);
}
extern int is_it_on(word)
char *word;
{
/** Returns TRUE if the specified word is either 'ON', 'YES'
or 'TRUE', and FALSE otherwise. We explicitly translate
to lowercase here to ensure that we have the fastest
routine possible
**/
char mybuffer[NLEN];
int i, j;
for (i=0, j=0; word[i] != '\0'; i++)
#ifdef ASCII_CTYPE
if (isascii(word[i]))
#endif
mybuffer[j++] = tolower((unsigned char)word[i]);
mybuffer[j] = '\0';
return( (strncmp(mybuffer, "on", 2) == 0) ||
(strncmp(mybuffer, "yes", 3) == 0) ||
(strncmp(mybuffer, "true", 4) == 0)
);
}
char * mode_to_str(mode)
int mode;
{
static char modestr[9+1]; /* "rwxrwxrwx\0" */
char *s = &modestr[0];
char *modecharp = "rwxrwxrwx";
int modebit = 0400;
while (modebit != 0) {
if (mode & modebit)
*s++ = *modecharp;
else
*s++ = '-';
modecharp++;
modebit >>= 1;
}
*s = '\0';
return(modestr);
}
int null_option_func(value,enter, lineno, filename)
char **value;
int enter;
int lineno;
char *filename;
{
return 0;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1