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 * (was hurtta+elm@ozone.FMI.FI) * or Kari Hurtta ***************************************************************************** * * 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 #ifndef ANSI_C extern int errno; #endif DEBUG_VAR(Debug,__FILE__,"config"); #ifdef PWDINSYS # include #else # include #endif #ifndef I_UNISTD char *getlogin(); unsigned short getgid(), getuid(); struct passwd *getpwuid(); #endif # ifdef DOUNAME # include # 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 : ""); 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 #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 : "")); } 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 : "")); } 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 : "")); } 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 : "")); } } } 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 : "")); 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 : "")); 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 : "")); } 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 : "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 : ""); 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: */