static char rcsid[] = "@(#)$Id: expand.c,v 1.22 2006/05/30 16:33:21 hurtta Exp $";

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

/** This is a library routine for the various utilities that allows
    users to have the standard 'Elm' folder directory nomenclature
    for all filenames (e.g. '+', '=' or '%').  It should be compiled
    and then linked in as needed.

**/

#include <stdio.h>
#include "headers.h"
#include "s_elmrc.h"

DEBUG_VAR(Debug,__FILE__,"config");

extern nl_catd elm_msg_cat;	/* message catalog	    */

int expand(filename, size)
     char *filename;
     int size;
{    
    if (filename[0] == '+' || filename[0] == '%' || filename[0] == '=') {
	char  buffer[SLEN];

	/* give_dt_estr_as_str adds / to end */
	char * str = give_dt_estr_as_str(&folders_e,"maildir");

	if (!str)
	    return 0;

	strfcpy(buffer,str, sizeof buffer);

	strfcat(buffer,filename+1, sizeof buffer);
  
	strfcpy(filename, buffer, size);	
    }
    return 1;
}

/* Returns 0 if no expansion done
           1 if expansion done
	  -1 on failure
*/
int expand_path(dest, src, destlen)
     char *dest;	/* pointer to space to hold the result	*/
     CONST char *src;	/* pointer to string to expand		*/
     unsigned destlen;	/* size of the destination buffer	*/
{
    CONST char *src0 = src;
    char *dest0 = dest;
    int check_for_env = TRUE;
    int ret = 0;	     /* assume success */

    if (destlen < 1) {
	DPRINT(Debug,1,(&Debug, 
			"expand_path()=-1, src=%s, destlen=%d\n", 
			src,destlen));
	return -1;	
    }
	
    --destlen;		/* reserve space for trailing '\0' */

    /*
     * Copy through the rest, performing $NAME expansion where appropriate.
     */

    while (destlen > 0 && *src != '\0') {

	/*
	 * Check for "$NAME" at the start of every path component.
	 */
	if (check_for_env && *src == '$') {
	    /*
	     * Get the environment parameter name into "envname_buf"
	     * and advance "src" to the next path component.
	     */
	    CONST char *envname_front = ++src;
	    CONST char *expval;
	    int len, p;
	    char envname_buf[SLEN];
    
	    if ((len = strcspn(src, "/@")) == 0)
		len = strlen(src);
	    src += len;
	    strnfcpy(envname_buf, envname_front, len, 
		     sizeof(envname_buf),NULL);

	    /*
	     * Copy over the environment expansion.  If the environment
	     * parameter is undefined then copy over unchanged and set
	     * a fail return status.
	     */
	    if ((expval = getenv(envname_buf)) == NULL) {
		*dest++ = '$';
		--destlen;
		expval = envname_buf;
		ret = -1;
		DPRINT(Debug,5,(&Debug,
			    "getenv(%s) FAILED\n",envname_buf));
	    } else {
		DPRINT(Debug,61,(&Debug,
				 "getenv(%s)=%s\n", 
				 envname_buf,expval));
	    }
	    len = strlen(expval);
	    strnfcpy(dest, expval, len, destlen,&p);
	    dest +=  p;
	    destlen -= p;
	    check_for_env = FALSE;

	    if (0 == ret)
		ret = 1;
	} else {

	    check_for_env = (*src == '/');
	    *dest++ = *src++;
	    --destlen;

	}
    }

    *dest = '\0';
    if (destlen <= 0)
	ret = -1;

    DPRINT(Debug,(ret == 0 ? 11: 5),(&Debug,
				     "expand_path()=%d, src=%s, dest=%s\n", 
				     ret,src0,dest0));
    
    return ret;
}

int expand_meta(dest, src, destlen)
     char *dest;	/* pointer to space to hold the result	*/
     CONST char *src;	/* pointer to string to expand		*/
     unsigned destlen;	/* size of the destination buffer	*/
{
    CONST char *src0 = src;
    char *dest0 = dest;
    CONST char * c;
    int ret = 0;

    if (destlen < 1) {
	DPRINT(Debug,1,(&Debug, 
		    "expand_meta()=-1, src=%s, destlen=%d\n", 
		    src,destlen));
	return -1;	
    }

    --destlen;		/* reserve space for trailing '\0' */

    if (src[0] == '+' || src[0] == '%' || src[0] == '=') {
	CONST char * expval;
	int len,p;

	/* give_dt_estr_as_str adds / to end */
	char * str = give_dt_estr_as_str(&folders_e,"maildir");

	if (!str) {
	    expval = "=";
	    ret = -1;
	    len = 1;
	} else {
	    expval = str;
	    len = strlen(str);
	}
	strnfcpy(dest, expval, len, destlen,&p);
	dest += p;
	destlen -= p;
	++src;

	if ('/' == src[0] && str) 
	    src++;

	if (expand_path(dest,src,destlen+1) < 0)
	    ret = -1;

    } else if (src[0] == '{' && NULL != (c = strpbrk(src,"}/")) &&
	       *c == '}' && *(c+1) == '/') {
	int l = (c - src) + 1;

	char result[STRING];
	int len,p;
	
	if (home[0] != '\0' && 4 == l && 0 == strncmp(src,"{rc}",l)) {
	    len = elm_sfprintf(result, sizeof result,
			       FRM("%s/.elm"),home);
	    src += l;
	} else if (5 == l && 0 == strncmp(src,"{lib}",l)) {
	    len = elm_sfprintf(result, sizeof result,
			       FRM("%s"),LIBHOME);
	    src += l;
	} else if (5 == l && 0 == strncmp(src,"{etc}",l)) {
	    len = elm_sfprintf(result, sizeof result,
			       FRM("%s"),ETCHOME);
	    src += l;
	} else if (5 == l && 0 == strncmp(src,"{bin}",l)) {
	    len = elm_sfprintf(result, sizeof result,
			       FRM("%s"),BINHOME);
	    src += l;
	} else if (5 == l && 0 == strncmp(src,"{doc}",l)) {
	    char * attachment_dir_val = 
		give_dt_estr_as_str(&attachment_dir_e,
				    "attachment-dir");
	    
	    if (!attachment_dir_val)
		attachment_dir_val = "";
	    
	    len = elm_sfprintf(result, sizeof result,
			       FRM("%s"),attachment_dir_val);
	    src += l;
	    if (!attachment_dir_val[0]) {
		DPRINT(Debug,3,(&Debug,
				"expand_meta: {doc} aka attachment-dir is not set\n"));
		ret = -1;
	    }
	} else {
	    strnfcpy(result,src,l,sizeof result,NULL);
	    len = l;
	    ret = -1;
	}
	strnfcpy(dest, result, len, destlen,&p);
	dest += p;
	destlen -= p;

	if (expand_path(dest,src,destlen+1) < 0)
	    ret = -1;

    } else {	
	if (expand_env(dest,src,destlen+1) < 0)
	    ret = -1;
    }

    DPRINT(Debug,(ret == 0 ? 10: 1),(&Debug,
				     "expand_meta()=%d, src=%s, dest=%s\n", 
				     ret,src0,dest0));

    return ret;   
}

/*
 * expand_env() - Perform environment expansion on a pathname.  Also
 * replaces "~" at the front of the path with the user's home directory.
 * Environment expansion occurs at the path component boundaries, e.g.
 * "/foo/$BAR/baz" is subject to expansion but "/foo/zzz$BAR/baz" is not.
 * Returns 0 if expansion successful, -1 if an error occurs (result too
 * long, cannot get home directory, or environment expansion failed).
 */
int expand_env(dest, src, destlen)
     char *dest;	/* pointer to space to hold the result	*/
     CONST char *src;	/* pointer to string to expand		*/
     unsigned destlen;	/* size of the destination buffer	*/
{
    int ret = 0;		/* assume success */
    CONST char *src0 = src;

    if (destlen < 1) {
	DPRINT(Debug,1,(&Debug, 
			"expand_env()=-1, src=%s, destlen=%d", 
			src,destlen));	
	return -1;	
    }
    --destlen;		/* reserve space for trailing '\0' */

    /*
     * Replace "~" at front with user's home directory.
     */
    if (src[0] == '~' && (src[1] == '\0' || src[1] == '/')) {
	CONST char *expval;
	int len, p;
	if (home[0] == '\0') {
	    expval = "~";
	    ret = -1;
	} else {
	    expval = home;
	}
	if ((len = strlen(expval)) > destlen)
	    len = destlen;
	strnfcpy(dest, expval, len, destlen, &p);
	dest +=  p;
	destlen -=  p;
	++src;
    }

    if (expand_path(dest,src,destlen+1) < 0)
	ret = -1;

    DPRINT(Debug,(ret == 0 ? 12: 4),(&Debug,
				     "expand_env()=%d, src=%s, dest=%s\n", 
				     ret,src0,dest));
    
    return ret;
}

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



syntax highlighted by Code2HTML, v. 0.9.1