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