static char rcsid[] = "@(#)$Id: ldstate.c,v 1.15 2006/05/01 09:18:57 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.15 $   $State: Exp $
 *
 *  Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI> 
 *                           (was hurtta+elm@ozone.FMI.FI)
 ******************************************************************************
 *  The Elm Mail System 
 *
 *			Copyright (c) 1992 USENET Community Trust
 *****************************************************************************/

#include "headers.h"

/*
 * Retrieve Elm folder state.
 *
 * The SY_DUMPSTATE option to "system_call()" causes Elm to dump the
 * current folder state before spawning a shell.  This allows programs
 * running as an Elm subprocess (e.g. "readmsg") to obtain information
 * on the folder.  (See the "system_call()" code for additional info
 * on the format of the state file.)
 *
 * This procedure returns -1 on the event of an error (corrupt state
 * file or malloc failed).
 *
 * A zero return does NOT necessarily mean that folder state information
 * was retrieved.  On a zero return, inspect the "folder_name" element.
 * If it was NULL then there was no state file found.  If it is non-NULL
 * then valid folder state information was found and loaded into
 * the (struct folder_state) record.
 */

#if !defined(ANSI_C) && !defined(atol)  /* avoid problems with systems that declare atol as a macro */
extern long atol();
#endif

#define LDSTATE_magic           0xF501

void zero_ldstate(fst)
     struct folder_state *fst;
{

    fst->magic     = LDSTATE_magic;
    fst->view      = NULL;
    fst->view_len  = 0;

    fst->storage      = 0;
    fst->storage_len  = 0;

    fst->sel_list  = NULL;
    fst->num_sel   = 0;
}


void zero_folder_view(X)
     struct folder_view *X;
{
    X->mailbox_number = 0;
    X->index          = 0;
    X->thread_number  = -1;

}


void clear_ldstate(fst)
     struct folder_state *fst;
{
     
    if (fst->magic     != LDSTATE_magic) 
  	panic("MBX PANIC",__FILE__,__LINE__,"clear_ldstate",
	      "bad magic number",0);

    if (fst->view) {
	free(fst->view);
	fst->view = NULL;
    }
    fst->view_len = 0;

    if (fst->storage) {
	int i;

	for (i = 0; i < fst->storage_len; i++) {
	    if (fst->storage[i].folder_name) {
		free(fst->storage[i].folder_name);
		fst->storage[i].folder_name = NULL;
	    }

	    if (fst->storage[i].mssgs) {
		free(fst->storage[i].mssgs);
		fst->storage[i].mssgs = NULL;
	    }

	    fst->storage[i].num_mssgs = 0;
	}


	free(fst->storage);
	fst->storage = NULL;
    }
    fst->storage_len = 0;

    if (fst->sel_list) {
	free (fst->sel_list);
	fst->sel_list = NULL;
    }
    fst->num_sel = 0;

}

static char *elm_fgetline P_((char *buf,
			      unsigned buflen,
			      FILE *fp));
static char *elm_fgetline(buf, buflen, fp)
     char *buf;
     unsigned buflen;
     FILE *fp;
{
    if (fgets(buf, buflen, fp) == NULL)
	return (char *) NULL;
    buf[strlen(buf)-1] = '\0';
    return buf;
}

int load_folder_state_file(fst)
     struct folder_state *fst;
{
    char buf[SLEN], *state_fname;
    int status, i, Len,j;
    FILE *fp;
    int err;

    /* clear out the folder status record */
    clear_ldstate(fst);

    /* see if we can find a state file */
    if ((state_fname = getenv(FOLDER_STATE_ENV)) == NULL)
	return 0;

    /* This test should not needed, 
       setgid Elm ME+ do not call this function
    */
    err = can_open(state_fname, "r");
    if (err)
	return 0;

    if ((fp = fopen(state_fname, "r")) == NULL)
	return 0;

    /* initialize status to failure */
    status = -1;

    /* Retrieve mailbox count */
    if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'S')
	goto done;
    fst->storage_len = atoi(buf+1);
    if (fst->storage_len < 1 || fst->storage_len > 9999)
	goto done;
    
    fst->storage = safe_malloc(fst->storage_len * sizeof (fst->storage[0]));
    for (i = 0; i < fst->storage_len; i++) {
	fst->storage[i].folder_name = NULL;
	fst->storage[i].num_mssgs = 0;
	fst->storage[i].mssgs = NULL;
    }

    for (j = 0; j < fst->storage_len; j++) {
	int n;
	/* retrieve filler */

	if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != '=')
	    goto done;
	
    again:
	n = atoi(buf+1);
	if (n < j || n >= fst->storage_len)
	    goto done;

	/* NOTE that storage/mailbox information may be missing ... */

	/* retrieve pathname of the folder */
	if (elm_fgetline(buf, sizeof(buf), fp) == NULL)
	    goto done;
	if ('=' == buf[0])
	    goto again;
	if ('V' == buf[0])
	    goto skip;
	if (buf[0] != 'F')
	    goto done;
	fst->storage[j].folder_name = safe_strdup(buf+1);
	
	/* retrieve number of messages in the folder */
	if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'N')
	    goto done;
	fst->storage[j].num_mssgs = atoi(buf+1);
	if (fst->storage[j].num_mssgs < 0 || 
	    fst->storage[j].num_mssgs > 999999)
	    goto done;
	if (!fst->storage[j].num_mssgs)
	    continue;
	
	/* allocate space to hold the indices */
	fst->storage[j].mssgs = 
	    safe_malloc(fst->storage[j].num_mssgs * 
			sizeof(fst->storage[j].mssgs[0]));
	
	for (i = 0 ; i < fst->storage[j].num_mssgs; i++) {
	    fst->storage[j].mssgs[i].idx = -1; 
	    fst->storage[j].mssgs[i].cl = -1; 
	}

	/* load in the indices of the messages */
	for (i = 0 ; i < fst->storage[j].num_mssgs ; ++i) {
	    if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'I')
		goto done;
	    if ('*' == buf[1]) {
		fst->storage[j].mssgs[i].idx = -1;
		fst->storage[j].mssgs[i].cl = -1;
	    } else {
		char *ptr;
		fst->storage[j].mssgs[i].idx = strtol(buf+1,&ptr,10);
		if (*ptr == ' ') 
		    fst->storage[j].mssgs[i].cl = atol(ptr+1);
		else
		    fst->storage[j].mssgs[i].cl = -1;
	    }
	}
    }

    /* load number of views */
    if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'V')
	goto done;
 skip:
    fst->view_len = atoi(buf+1);
    if (fst->view_len < 0 || fst->view_len > 9999999)
	goto done;
    
    if (fst->view_len > 0) {
	int i;

	fst->view = safe_malloc(fst->view_len * sizeof(fst->view[0]));
	for (i = 0; i < fst->view_len; i++) 
	    zero_folder_view(& (fst->view[i]));

	for (i = 0; i < fst->view_len; i++) {
	    int r;
	    /* Get mailbox number and index and possible thread number */

	    if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'i')
		goto done;

	    r = sscanf(buf+1,"%d %d %d",
		       & fst->view[i].mailbox_number,
		       & fst->view[i].index,
		       & fst->view[i].thread_number
		       );
	    if (2 == r)
		fst->view[i].thread_number = -1;
	    else if (3 != r)
		goto done;
	}
    }

    /* load in the number of messages selected */
    if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'C')
	goto done;
    fst->num_sel = atoi(buf+1);

    /* it is possible that there are no selections */
    if (fst->num_sel > 0) {

	/* allocate space to hold the list of selected messages */
	fst->sel_list = (int *) safe_malloc(fst->num_sel * sizeof(int));

	/* load in the list of selected messages */
	for (i = 0 ; i < fst->num_sel ; ++i) {
	    if (elm_fgetline(buf, sizeof(buf), fp) == NULL || buf[0] != 'S')
		goto done;
	    fst->sel_list[i] = atoi(buf+1);
	}

    }

    /* that should be the end of the file */
    if (elm_fgetline(buf, sizeof(buf), fp) != NULL)
	goto done;

    /* success */
    status = 0;

done:
    (void) fclose(fp);
    return status;
}

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


syntax highlighted by Code2HTML, v. 0.9.1