static char rcsid[] = "@(#)$Id: init.c,v 1.73 2006/08/26 14:52:02 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.73 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
/***** Initialize - read in all the defaults etc etc
*****/
#include "def_elm.h"
#include "patchlevel.h"
#include "s_elm.h"
#include "s_me.h"
DEBUG_VAR(Debug,__FILE__,"ELM");
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
#ifdef PWDINSYS
# include <sys/pwd.h>
#else
# include <pwd.h>
#endif
#include <errno.h>
#ifndef ANSI_C
extern int errno; /* system error number on failure */
#endif
extern char version_buff[];
SIGHAND_TYPE
#ifdef SIGTSTP
sig_user_stop P_((int)), sig_return_from_user_stop P_((int)),
#endif
#ifdef SIGWINCH
winch_signal P_((int)),
#endif
quit_signal P_((int)), term_signal P_((int)), ill_signal P_((int)),
fpe_signal P_((int)), segv_signal P_((int)),
#ifdef SIGBUS
bus_signal P_((int)),
#endif
alarm_signal P_((int)), pipe_signal P_((int)), hup_signal P_((int)),
usr1_signal P_((int)), usr2_signal P_((int)) ;
static struct folder_info *arg_to_folder P_((char * arg, int prompt,
struct AliasView *aview,
struct menu_context *page));
static struct folder_info *arg_to_folder(arg,prompt,aview, page)
char * arg;
int prompt;
struct AliasView *aview;
struct menu_context *page;
{
struct folder_info *folder = NULL;
/* Assuming that file name given with -f is on
local-fs-charset and not system_charset
*/
struct folder_browser * XXX = new_browser(selection_folder);
struct string * buffer = new_string2(local_fs_charset,
s2us(arg));
if (!browser_expand(XXX,&buffer,NULL,aview)) {
if (!prompt)
goto cleanup;
if (with_title)
with_title = "";
gen_browser(page, XXX,&buffer,word_change,NULL,
aview,
CATGETS(elm_msg_cat, ElmSet,
ElmSelectFolder,
"Select folder: "));
}
/* Returns 0 if no selection */
if (!give_dir_flags(XXX)) {
goto cleanup;
}
folder = folder_from_dir_item(XXX);
if (!folder)
goto cleanup;
if (!sessionlock_folder(folder,SESSIONLOCK_CHECK)) {
DPRINT(Debug,1,
(&Debug,
"Error: given file %s as folder - unreadable (%s)!\n",
folder->cur_folder_sys, error_description(errno)));
/* Free folder structure */
leave_old_folder (&folder,CLOSE_NORMAL);
}
cleanup:
if (buffer)
free_string(&buffer);
free_dir(&XXX);
return folder;
}
void initialize(main_aliases,
page)
struct AliasView **main_aliases;
struct menu_context **page;
{
int init_scr_return;
char buffer[SLEN], *cp;
elm_sfprintf(version_buff, sizeof version_buff,
FRM("%s PL%s"), VERSION, PATCHLEVEL);
def_ans_yes = catgets(elm_msg_cat, ElmSet, ElmYes, "y");
def_ans_no = catgets(elm_msg_cat, ElmSet, ElmNo, "n");
nls_deleted = catgets(elm_msg_cat, ElmSet, ElmTitleDeleted, "[deleted]");
nls_form = catgets(elm_msg_cat, ElmSet, ElmTitleForm, "Form");
nls_message = catgets(elm_msg_cat, ElmSet, ElmTitleMessage, "Message");
nls_to = catgets(elm_msg_cat, ElmSet, ElmTitleTo, "To");
nls_from = catgets(elm_msg_cat, ElmSet, ElmTitleFrom, "From");
nls_page = catgets(elm_msg_cat, ElmSet, ElmTitlePage, " Page %d");
change_word = catgets(elm_msg_cat, ElmSet, ElmChange, "change");
save_word = catgets(elm_msg_cat, ElmSet, ElmSave, "save");
copy_word = catgets(elm_msg_cat, ElmSet, ElmCopy, "copy");
cap_save_word = catgets(elm_msg_cat, ElmSet, ElmCapSave, "Save");
cap_copy_word = catgets(elm_msg_cat, ElmSet, ElmCapCopy, "Copy");
saved_word = catgets(elm_msg_cat, ElmSet, ElmSaved, "saved");
copied_word = catgets(elm_msg_cat, ElmSet, ElmCopied, "copied");
Stopped_Text = catgets(elm_msg_cat, ElmSet, ElmStoppedUseFGToReturn,
"\n\nStopped. Use \"fg\" to return to ELM\n\n");
Back_Text = catgets(elm_msg_cat, ElmSet, ElmBackInElmRedraw,
"\nBack in ELM. (You might need to explicitly request a redraw.)\n\n");
Segv_Text = catgets(elm_msg_cat, ElmSet, ElmSegmentViolationSignal,
"\n\nSegment Violation signal!\n\n");
Bus_Text = catgets(elm_msg_cat, ElmSet, ElmBusErrorSignal,
"\n\nBus Error signal!\n\n");
Fpe_Text = catgets(elm_msg_cat, ElmSet, ElmFloatingPointSignal,
"\n\nFloating Point Exception signal!\n\n");
Ill_Text = catgets(elm_msg_cat, ElmSet, ElmIllegalInstructionSignal,
"\n\nIllegal Instruction signal!\n\n");
/*
* Install the error trap to take if xmalloc() or friends fail.
*/
safe_malloc_fail_handler = malloc_failed_exit;
init_opts_menu();
init_scr_return = InitScreen(page);
out_util_setup();
/* make all newly created files private */
original_umask = umask(077);
/* get username and home directory */
user_init();
/* user_init sets have_saved_ids, mailgroupid, userid and groupid */
if (have_saved_ids) {
DPRINT(Debug,4,(&Debug,
"*** setting gid=%d (mailgroupid=%d)\n",
groupid,mailgroupid));
if (setgid(groupid) < 0) {
int err = errno;
lib_error(FRM("init: setgid(%d) FAILED: %s"),
groupid,error_description(err));
}
}
#ifdef DEBUG
{
int d = panic_dprint("\n\
======================================================\n\
Debug output of the ELM program (version %s).\n",
version_buff);
if (d >= 50) {
panic_dprint("WARNING: Edit manually out sensitive information from that file!\n");
lower_prompt("WARNING: Debug file may include passwords -- edit it!");
error_sleep(5+sleepmsg);
}
}
/*
* If debug level is fairly low, ignore keyboard signals
*/
/* FIXME -- Probably wrong variable ... */
if (Debug.active < 5) {
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
}
#else
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
#endif
if(!check_only && !batch_only) {
if (init_scr_return < 0) {
if (init_scr_return == -1) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNoTerm,
"Sorry, but you must specify what type of terminal you're on if you want to\n\
run the \"elm\" program. (You need your environment variable \"TERM\" set.)\n"));
DPRINT(Debug,1,
(&Debug,
"No $TERM variable in environment!\n"));
}
else if (init_scr_return == -2) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmBadTerm,
"You need a cursor-addressable terminal to run \"elm\" and I can't find any\n\
kind of termcap entry for \"%s\" - check your \"TERM\" setting...\n"),
getenv("TERM"));
DPRINT(Debug,1,
(&Debug,
"$TERM variable is an unknown terminal type!\n"));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmTermInitFailed,
"Failed trying to initialize your terminal entry: unknown return code %d\n"),
init_scr_return);
DPRINT(Debug,1,
(&Debug,
"Initscreen returned unknown code: %d\n",
init_scr_return));
}
error_wait(); /* Be sure that we do not exit before error is shown */
exit(1); /* all the errors share this exit statement */
}
}
#ifdef DEBUG
/* FIXME -- Probably wrong variable ... */
if (Debug.active < 5) { /* otherwise let the system trap 'em! */
init_signals();
}
else {
DPRINT(Debug,3,
(&Debug,
"\n*** Elm-Internal Signal Handlers Disabled due to debug level %d ***\n\n",
Debug.active));
}
#else
init_signals();
#endif
init_signals1();
#ifdef BACKGROUD_PROCESSES
init_backgroud_handling();
#endif
init_mailerlib();
init_mboxlib();
init_misclib();
/* Determine options that might be set in the global elmrc */
if (init_defaults() != 0) {
sleep(1);
}
/* Determine options that might be set in the .elm/elmrc */
if (read_rc_file(0) != 0) {
sleep(1);
if (!batch_only && !write_elmrc) {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmFixElmrc,
"Fix %s, %s, %s, %s, %s and/or %s or let elm rebuild them with option '-w'."),
ELMRCFILE, USER_MIME_CHARSETS,
USER_TERMINAL_INFO, USER_MAIL_SERVICES,
USER_ISO2022_SETS, USER_MIME_TYPES
);
error_wait(); /* Be sure that we do not exit before error is shown */
exit(1);
}
}
*main_aliases = new_aliasview();
add_files_to_aview(*main_aliases);
if (check_only) {
DPRINT(Debug,5,
(&Debug,
"initialize: check_only (-c) -- skipping rest of initialize.\n"));
return;
}
if (!Check_attachments()) {
error_wait(); /* Be sure that we do not exit before error is shown */
exit(1);
}
/* Check if .elm and Mail directories exists */
directory_check();
if (write_elmrc) {
int err;
FILE *f = NULL;
char *tmp;
save_options();
tmp = elm_message(FRM("%s.N"),user_iso2022_sets);
err = can_open(tmp,"w");
if (err)
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
else if (!(f = fopen(tmp,"w"))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else {
dump_iso2022_map(f,ml_user);
if (EOF == fclose(f)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else if (0 != rename(tmp,user_iso2022_sets)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %30s"),
user_iso2022_sets,
error_description(err));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmISO2022SavedIn,
"ISO 2022 mappings saved in file %s."),
user_iso2022_sets);
}
}
free(tmp);
tmp = elm_message(FRM("%s.N"),user_mime_charsets);
err = can_open(tmp,"w");
if (err)
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
else if (!(f = fopen(tmp,"w"))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else {
dump_charset_map(f,user_charset_map);
if (EOF == fclose(f)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else if (0 != rename(tmp,user_mime_charsets)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %30s"),
user_mime_charsets,
error_description(err));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmCharsetsSavedIn,
"Charsets saved in file %s."),
user_mime_charsets);
}
}
free(tmp);
tmp = elm_message(FRM("%s.N"),user_terminal_info);
err = can_open(tmp,"w");
if (err)
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
else if (!(f = fopen(tmp,"w"))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else {
dump_terminal_map(f,user_terminal_map);
if (EOF == fclose(f)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else if (0 != rename(tmp,user_terminal_info)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %30s"),
user_terminal_info,
error_description(err));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmTerminalInfoSavedIn,
"Additional terminal info saved in file %s."),
user_terminal_info);
}
}
free(tmp);
#ifdef REMOTE_MBX
tmp = elm_message(FRM("%s.N"),user_mail_services);
err = can_open(tmp,"w");
if (err)
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
else if (!(f = fopen(tmp,"w"))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else {
dump_service_entries(f,0 /* USER */);
if (EOF == fclose(f)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else if (0 != rename(tmp,user_mail_services)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %30s"),
user_mail_services,
error_description(err));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmMailServInfoSavedIn,
"Mail service info saved in file %s."),
user_mail_services);
}
}
free(tmp);
#endif
tmp = elm_message(FRM("%s.N"),user_mime_types);
err = can_open(tmp,"w");
if (err)
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
else if (!(f = fopen(tmp,"w"))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else {
dump_mime_types_map(f,user_mimetypes_map);
if (EOF == fclose(f)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmp, error_description(err));
} else if (0 != rename(tmp,user_mime_types)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %30s"),
user_terminal_info,
error_description(err));
} else {
lib_error(CATGETS(elm_msg_cat, ElmSet,
ElmContentTypeInfoSavedIn,
"Content-type mapping info saved in file %s."),
user_mime_types);
}
}
free(tmp);
error_sleep(1);
}
/** check to see if the user has defined a LINES or COLUMNS
value different to that in the termcap entry (for
windowing systems, of course!) **/
{
int lines = -1;
int columns = -1;
if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
sscanf(cp, "%d", &lines);
}
if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
sscanf(cp, "%d", &columns);
set_root_menu(lines,columns);
/* And read changes what just implied */
menu_resized(*page);
}
/* Now that we've read the rc file we can enter RAW mode */
if (!batch_only) {
Raw(ON);
/** clear the screen **/
menu_ClearScreen(*page);
}
init_system_charset();
if (-1 != wanted_switchmode)
allow_charset_switching = wanted_switchmode;
if (init_scr_return >= 0) {
if (wanted_charset) {
charset_t X = MIME_name_to_charset(wanted_charset,0);
if (!X) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmArgsCharsetUnknown,
"Charset %s given with -D flag is unknown."),
wanted_charset);
} else if (set_display_charset(X,0)) {
CarriageReturn();
Write_to_screen(CATGETS(elm_msg_cat, ElmSet,
ElmDisplayCharsetChanged,
"[display charset changed to %s]"),
wanted_charset);
CarriageReturn();
} else {
DPRINT(Debug,1,
(&Debug,
"No way to set terminal to charset %s (-D option)\n",
wanted_charset));
}
} else if (wanted_display_charset &&
wanted_display_charset != system_charset) {
if (set_display_charset(wanted_display_charset,1)) {
CarriageReturn();
Write_to_screen(CATGETS(elm_msg_cat, ElmSet,
ElmDisplayCharsetChanged,
"[display charset changed to %s]"),
display_charset -> MIME_name ?
display_charset -> MIME_name :
"<no MIME name>");
CarriageReturn();
}
}
if (wanted_title_string || wanted_icon_string) {
if (! set_terminal_titles(wanted_title_string,
wanted_icon_string)) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmArgsTitleNoSet,
"Title (or icon) name for terminal can not set"));
}
}
if (with_title && with_title[0]) {
if (! set_terminal_titles(with_title,NULL)) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmArgsTitleNoSet1,
"Title name for terminal can not set"));
}
}
}
post_process_charset_options();
#ifdef DEBUG
if (Debug.active >= 2 && Debug.active < 10) {
debug_action_call(&Debug,
"hostname = %-20s \tusername = %-20s \tfullname = %-20s\n",
hostname, username, full_username);
debug_action_call(&Debug,
"home = %-20s \n",
home);
debug_action_call(&Debug,
" \tprefix = %-20s \t\n\n",
prefixchars);
}
#endif
}
static int ok_to_open_mailbox P_((struct MailboxView *main_mailbox,
enum check_mode check_mode));
static int ok_to_open_mailbox(main_mailbox,check_mode)
struct MailboxView *main_mailbox;
enum check_mode check_mode;
{
if (chk_size == check_mode ||
chk_unread == check_mode) {
int mc = get_message_count(main_mailbox);
if (0 == mc) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNoMail,
"You have no mail."));
return 0;
}
}
if (chk_unread == check_mode) {
int i;
int unread = 0;
int mc = get_message_count(main_mailbox);
for (i = 0; i < mc; i++) {
if (ison_status_message(main_mailbox,i,status_basic,UNREAD))
unread++;
}
if (!unread) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNoUnreadMail,
"You have no unread mail."));
return 0;
}
}
return 1;
}
struct MailboxView * initialize_mailbox(requestedmfiles,
page, main_aliases,
check_mode)
char **requestedmfiles; /* first mail files to open, empty if the default */
struct menu_context *page;
struct AliasView *main_aliases;
enum check_mode check_mode;
{
struct MailboxView *main_mailbox = NULL;
struct folder_info *folder = NULL;
int several_folders = 0;
/* Determine the mail file to read */
if (!requestedmfiles || ! requestedmfiles[0]) {
char * default_val = give_dt_estr_as_str(&defaultfile_e,
"incoming-mailbox");
if (default_val)
folder = enter_new_folder(default_val);
else
folder = NULL;
} else {
/* Assuming that file name given with -f is on
local-fs-charset and not system_charset
*/
if (requestedmfiles[1])
several_folders++;
folder = arg_to_folder(requestedmfiles[0], !several_folders,
main_aliases, page);
}
if (!folder && !several_folders) {
return NULL;
}
if (folder) {
if (chk_size == check_mode && !several_folders) {
if(check_mailfile_size(folder) != 0) {
leave_old_folder(&folder,CLOSE_NORMAL);
return NULL;
}
}
if (with_title)
set_folder_window_title(folder,
with_title[0] ? with_title : wanted_title_string,
wanted_icon_string);
else if (set_window_title)
set_folder_window_title(folder,
wanted_title_string,
wanted_icon_string);
/* read in the folder! */
newmbox_1(folder, &main_mailbox, FALSE,
page);
}
if (several_folders) {
int i;
/* Index 0 is already processed! */
for (i = 1; requestedmfiles[i]; i++) {
struct folder_info *folder =
arg_to_folder(requestedmfiles[i],FALSE,main_aliases,
page);
if (folder) {
newmbox_1(folder, &main_mailbox,
main_mailbox ? TRUE : FALSE,
page);
}
}
if (main_mailbox && wanted_mailbox_title) {
/* must not fred -- shared/stored to structure
-- set_mailbox_title will free_string()
it later */
set_mailbox_title(main_mailbox,
new_string2(system_charset,
s2us(wanted_mailbox_title)));
}
}
if (!main_mailbox)
return NULL;
if (!ok_to_open_mailbox(main_mailbox,check_mode)) {
/* This also free's folder */
free_mailbox(& main_mailbox);
return NULL;
}
return main_mailbox;
}
/* May not be
uin16 port
because this is promoted to int
*/
/* Return 1 for open */
static int no_verify_remote_url P_((const struct url *url,
const struct string * user,
const struct string * host,
struct string ** anon_passwd, /* prompt for 'anon password' */
int port,
int default_port));
static int no_verify_remote_url(url,user,host,anon_passwd,port,default_port)
const struct url *url;
const struct string * user;
const struct string * host;
struct string ** anon_passwd; /* prompt for 'anon password' */
int port;
int default_port;
{
return 1;
}
struct MailboxView * initialize_mailbox_from_url(url,page,check_mode,ask)
struct url * url;
struct menu_context *page;
enum check_mode check_mode;
int ask;
{
struct MailboxView *main_mailbox = NULL;
struct folder_info *folder = get_folder_from_url(url,
ask ? verify_remote_url :
no_verify_remote_url);
if (!folder)
return NULL;
if (chk_size == check_mode) {
if(check_mailfile_size(folder) != 0) {
goto fail;
}
}
/* folder is set to NULL, if it is not needed
to free
read in the folder!
*/
main_mailbox = enter_mailbox(&folder,page);
if (!main_mailbox)
goto fail;
if (!ok_to_open_mailbox(main_mailbox,check_mode)) {
/* This also free's folder */
free_mailbox(& main_mailbox);
}
fail:
if (folder)
leave_old_folder(&folder,CLOSE_NORMAL);
return main_mailbox;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1