static char rcsid[] = "@(#)$Id: utils.c,v 1.40 2006/04/09 07:37:19 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.40 $   $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
 *****************************************************************************/

/** Utility routines for ELM

**/

#include "def_elm.h"
#include "s_elm.h"

DEBUG_VAR(Debug,__FILE__,"ELM");

#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif       

void create_new_folders()
{
    /* give_dt_estr_as_str adds / to end */
    char * folders_val = give_dt_estr_as_str(&folders_e,"maildir");

    /* this creates a new folders directory */

    (void) mkdir(folders_val, 0700);

    (void) elm_chown(folders_val, userid, groupid);
}

void create_new_elmdir()
{
	/** this routine is just for allowing new users who don't have the
	    old elm files to create a new .elm directory **/

	char source[SLEN];
	elm_sfprintf(source, sizeof source,
		     FRM("%s/.elm"), home);
	(void) mkdir(source, 0700);

	(void) elm_chown( source, userid, groupid);
}


/*
 * The initialize() procedure sets the "xalloc_fail_handler" vector to
 * point here in the event that xmalloc() or friends fail.
 */
/*ARGSUSED*/
void malloc_failed_exit(proc, len)
     char *proc;
     unsigned len;
{
    int LINES, COLUMNS;

    menu_get_sizes(default_context, &LINES, &COLUMNS);   

    MoveCursor(LINES-1,0);
    Raw(OFF);

    /* NOTE:
       Can't use elm_fprintf (or routines of lib/output.c)
       because here also malloc may fail, therefore
       can not use CATGETS macro;
       And can't use catgets because it may have given 
       incorrent format string from catalog ...

       Same problem also with Write_to_screen() on src/curses.c 
       ... perhaps should use WriteRaw() from src/curses.c
    */
    FlushBuffer();

    fprintf(stderr,"\n\nCouldn't malloc %d bytes!!\n\n", len);

    /* SIGDPRINT does not call malloc */

    SIGDPRINT(Debug,1, (&Debug, "Couldn't malloc %d bytes!!\n",len));
    
    panic("PANIC",__FILE__,__LINE__,"malloc_failed_exit",
	  "Out of memory",0);
}

static void leave_cursor P_((int interrupt));
static void leave_cursor(interrupt)
     int interrupt;
{
    /* MoveCursor() is not safe on interrupt */

   if (interrupt) {
       ClearScreen(0);
       Raw(OFF|RAW_FROM_SIGNAL);
    } else {
	
	Raw_OFF(0);
    }

}

/* Tjis routine is called by panic() */
void emergency_exit(interrupt)
     int interrupt;
{
    struct MailboxView *m;
    int idx = 0;

    /* if interrupt is true we can't call anything which 
     * is not reentrant 
     */

    /** used in dramatic cases when we must leave without altering
	ANYTHING about the system... **/

    int do_cursor = RawState();

    /*
     *	some OS's get extra cont signal, so once this far into the
     *	exit, ignore those signals (Especially Ultrix)
     */

#ifdef SIGTSTP
    signal(SIGTSTP,SIG_IGN);
#endif
#ifdef SIGSTOP
    signal(SIGSTOP,SIG_IGN);
#endif
#ifdef SIGCONT
    signal(SIGCONT,SIG_IGN);
#endif

    if (interrupt)
	SIGDPRINT(Debug,1, (&Debug,  
			    "\nLeaving mailer from signal handler (emergency_exit)\n"));
    
    SIGDPRINT(Debug,1, (&Debug,  
			"\nERROR: Something dreadful is happening!  Taking emergency exit!!\n\n"));
    SIGDPRINT(Debug,1, (&Debug,  
			"  possibly leaving behind the following files;\n"));
    
    while (NULL != (m = give_next_open_mailbox(&idx,interrupt))) {
	int mc = get_storage_count(m);
	int i;

	for (i = 0; i < mc; i++) {
	    struct current_storage * storage = get_storage(m,i);

	    if (storage && storage->current_folder) {
		SIGDPRINT(Debug,1, (&Debug,  
				    "     The mailbox temp file : %s\n", 
				    storage->current_folder->cur_tempfolder));
	    }
	}
    }
    
    SIGDPRINT(Debug,1, (&Debug,  
			"     The composition file : %s\n", 
			cur_editfile));
    
	/* softkeys_off(); */

    /* MoveCursor() is not safe to be called from interrupt */
    if (do_cursor) 
	leave_cursor(interrupt);

    /* lib_error is not safe to be called from signal handler */
    if (!interrupt)
	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmEmergencyExitTaken,
			  "\nEmergency exit taken! All temp files intact!\n\n"));
    else
	WriteRaw("\nEmergency exit taken! All temp files intact!\n\n");

#ifdef USE_PGP
    /* Don't put passphrase to core file! */
    pgp_void_passphrase();
#endif

    /* This routine is called by panic() so 
       DO NOT call panic on here ...
    */
	    
    if (interrupt) {
	WriteRaw("\nABORTING...\n");
	abort();
    }

    exit(127);
}

void rm_temps_exit()
{
    int do_cursor = RawState();
    int LINES, COLUMNS;

    menu_get_sizes(default_context, &LINES, &COLUMNS);   

/*
 *	some OS's get extra cont signal, so once this far into the
 *	exit, ignore those signals (Especially Ultrix)
 */
#ifdef SIGTSTP
    signal(SIGTSTP,SIG_IGN);
#endif
#ifdef SIGSTOP
    signal(SIGSTOP,SIG_IGN);
#endif
#ifdef SIGCONT
    signal(SIGCONT,SIG_IGN);
#endif

    PutLineX(LINES-1, 0, 
	     CATGETS(elm_msg_cat, ElmSet, ElmWriteFailedExitingIntact,
		     "\nWrite to temp file failed, exiting leaving mailbox intact!\n\n"));

    SIGDPRINT(Debug,1, (&Debug,   
			"\nrm_temps_exit, deleteing temp files\n"));
    
    /* softkeys_off(); */

    if (cur_editfile[0])
	unlink(cur_editfile); /* editor buffer */

    free_all_mailboxes();
    free_all_aliasviews();

#ifdef REMOTE_MBX
    close_cached_connections();
#endif

    if(do_cursor) {
	Raw_OFF(1);
    }

    exit(1);
}

/*ARGSUSED*/
/*VARARGS0*/

static void mailbox_unlock P_((int interrupt));
static void mailbox_unlock(interrupt)
     int interrupt;
{
    struct MailboxView *m;
    int idx = 0;

    while (NULL != (m = give_next_open_mailbox(&idx,interrupt))) {
	int mc = get_storage_count(m);
	int i;


	for (i = 0; i < mc; i++) {
	    struct current_storage * storage = get_storage(m,i);
	    if (storage) {
		if (storage->current_folder) {
		    unlock(interrupt, storage->current_folder);	/* remove lock file if any */
		    
		}
	    }
	}	    
    }
}

static void mailbox_close P_((int interrupt));
static void mailbox_close(interrupt)
     int interrupt;
{

    mailbox_unlock(interrupt);

    if (!interrupt)
	free_all_mailboxes();
}


void leave(interrupt)
     int interrupt;
{
    int do_cursor = RawState();
    /* if interrupt is true do not call anything which is not re-entrant */  

    /*
     *	some OS's get extra cont signal, so once this far into the
     *	exit, ignore those signals (Especially Ultrix)
     */
#ifdef SIGTSTP
    signal(SIGTSTP,SIG_IGN);
#endif
#ifdef SIGCONT
    signal(SIGCONT,SIG_IGN);
#endif

    if (interrupt) 
	 SIGDPRINT(Debug,2, 
		   (&Debug,  
		    "\nLeaving mailer from signal handler (leave)\n"));
    else {
	SIGDPRINT(Debug,2, (&Debug, 
			    "\nLeaving mailer normally (leave)\n"));
    }

    /* Set terminal title to "Elm: exiting" ... can be called from
       signal handler
    */
    switch_title(2);

    /* softkeys_off(); */

    if (cur_editfile[0])
	unlink(cur_editfile); /* editor buffer */
 
    mailbox_close(interrupt);

    
    if (!interrupt)
	free_all_aliasviews();
    

#ifdef REMOTE_MBX
    if (!interrupt)
	close_cached_connections();
#endif
    
    /* MoveCursor() is not safe to be called from interrupt */
    if (do_cursor) 
	leave_cursor(interrupt);

    if (!interrupt)
	exit(0);
    _exit(0);
}

void silently_exit()
{
    /** This is the same as 'leave', but it doesn't remove any non-pid
	files.  It's used when we notice that we're trying to create a
	temp mail file and one already exists!!
    **/
    int do_cursor = RawState();
	
/*
 *	some OS's get extra cont signal, so once this far into the
 *	exit, ignore those signals (Especially Ultrix)
 */
#ifdef SIGTSTP
    signal(SIGTSTP,SIG_IGN);
#endif
#ifdef SIGSTOP
    signal(SIGSTOP,SIG_IGN);
#endif
#ifdef SIGCONT
    signal(SIGCONT,SIG_IGN);
#endif

    DPRINT(Debug,2, (&Debug, "\nLeaving mailer quietly (silently_exit)\n"));

    /* softkeys_off(); */
    
    if (cur_editfile[0])
	unlink(cur_editfile);

    if (do_cursor) {
	Raw_OFF(1);
    }

    mailbox_unlock(0);

    free_all_aliasviews();

#ifdef REMOTE_MBX
    close_cached_connections();
#endif
    
    exit(0);
}

/*ARGSUSED0*/

#ifndef REMOVE_AT_LAST
void leave_locked()
{
    struct MailboxView *m;
    int idx = 0;

    /** same as leave routine, but don't disturb lock file **/

    int do_cursor = RawState();
    
    /*
     *	some OS's get extra cont signal, so once this far into the
     *	exit, ignore those signals (Especially Ultrix)
     */
#ifdef SIGTSTP
    signal(SIGTSTP,SIG_IGN);
#endif
#ifdef SIGSTOP
    signal(SIGSTOP,SIG_IGN);
#endif
#ifdef SIGCONT
    signal(SIGCONT,SIG_IGN);
#endif
    
    SIGDPRINT(Debug,3, (&Debug, 
			"\nLeaving mailer due to presence of lock file (leave_locked)\n"));

    /* softkeys_off(); */

    if (cur_editfile[0])
	unlink(cur_editfile); /* editor buffer */

    while (NULL != (m = give_next_open_mailbox(&idx,0))) {
	int mc = get_storage_count(m);
	int i;


	for (i = 0; i < mc; i++) {
	    struct current_storage * storage = get_storage(m,i);

	    if (storage && storage->current_folder) {
		leave_old_folder(& storage->current_folder,CLOSE_LEAVE_LOCKED);
	    }
	}
    }

    free_all_aliasviews();

#ifdef REMOTE_MBX
    close_cached_connections();
#endif

    if (do_cursor) {
	Raw_OFF(1);
    }
    
    exit(0);
}
#endif

void get_page(menu, header_page)
     struct menu_common *menu;
     struct menu_context  *header_page;
{
    /** Ensure that 'current' is on the displayed page,**/

    int current = mcommon_get_current(menu);
    int top      = menu_header_get(header_page,header_top_line);
    int topO     = top;
    int j        = menu_header_get(header_page,header_current);


    /* but what is it on the SCREEN??? */
    int msg_pointer = compute_visible(current, menu) -1;

    int li,co;


    if (j != msg_pointer) {
	DPRINT(Debug,5,(&Debug,  
			"get_page: current %d: header_page current %d => %d\n",
			current,j,msg_pointer));
	menu_header_change(header_page, header_current,msg_pointer);
    }


    menu_get_sizes(header_page, &li, &co);   

    if (msg_pointer >= top+li) {
	top = msg_pointer;

	DPRINT(Debug,5,(&Debug,  
			"get_page: current %d: header_page top %d => %d\n",
			current,topO,top));

	menu_header_change(header_page, header_top_line,top);
    }

    if (msg_pointer < top) {
	
	top -= li;

	if (msg_pointer < top)
	    top = msg_pointer -2;

	if (top < 0)
	    top = 0;

	DPRINT(Debug,5,(&Debug,  
			"get_page: current %d: header_page top %d => %d\n",
			current,topO,top));

	menu_header_change(header_page, header_top_line,top);
    }
}

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1