Commit 3da084d7 authored by Richard Curnow's avatar Richard Curnow

Implement home dir and environment var expansion for .mairixrc file

Original rev  : rc@rc0.org.uk--2004-mairix/mairix--dev--0.16--patch-1
parent 4d46790b
......@@ -45,7 +45,7 @@ docdir=$(DESTDIR)@docdir@
OBJ = mairix.o db.o rfc822.o tok.o hash.o dirscan.o writer.o \
reader.o search.o stats.o dates.o datescan.o mbox.o md5.o \
fromcheck.o glob.o dumper.o
fromcheck.o glob.o dumper.o expandstr.o
all : mairix
......
NEW IN VERSION 0.16
===================
* Home directory and environment variable expansion in the .mairixrc file
NEW IN VERSION 0.15
===================
......
......@@ -114,7 +114,7 @@ void dump_database(char *filename)
printf("--------------------------------\n");
dump_toktable(db, &db->to, "To");
printf("--------------------------------\n");
dump_toktable(db, &db->cc, "To");
dump_toktable(db, &db->cc, "Cc");
printf("--------------------------------\n");
dump_toktable(db, &db->from, "From");
printf("--------------------------------\n");
......
/*
mairix - message index builder and finder for maildir folders.
**********************************************************************
* Copyright (C) Richard P. Curnow 2004
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
**********************************************************************
*/
#include "mairix.h"
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <ctype.h>
static int isenv(unsigned char x)/*{{{*/
{
/* Return true if x is valid as part of an environment variable name. */
if (isalnum(x))
return 1;
else if (x == '_')
return 1;
else
return 0;
}
/*}}}*/
static int home_dir_len(void)/*{{{*/
{
struct passwd *foo;
foo = getpwuid(getuid());
return strlen(foo->pw_dir);
}
/*}}}*/
static char *env_lookup(const char *p, const char *q)/*{{{*/
{
char *var;
char *lookup, *result;
char *s;
var = new_array(char, (q-p)+1);
for (s=var; p<q; p++, s++) {
*s = *p;
}
*s = 0;
lookup = getenv(var);
if (lookup) {
result = new_string(lookup);
} else {
result = NULL;
}
free(var);
return result;
}
/*}}}*/
static int env_lookup_len(const char *p, const char *q) {/*{{{*/
char *foo;
int len;
foo = env_lookup(p, q);
if (!foo) len = 0;
else {
len = strlen(foo);
free(foo);
}
return len;
}
/*}}}*/
static int compute_length(const char *p)/*{{{*/
{
const char *q;
int first;
int len;
first = 1;
len = 0;
while (*p) {
if (first && (*p == '~') && (p[1] == '/')) {
/* Make no attempt to expand ~other_user form */
len += home_dir_len();
p++;
} else if ((*p == '$') && (p[1] == '{')) {
p += 2;
q = p;
while (*q && (*q != '}')) q++;
len += env_lookup_len(p, q);
p = *q ? (q + 1) : q;
} else if (*p == '$') {
p++;
q = p;
while (*q && isenv(*(unsigned char*)q)) q++;
len += env_lookup_len(p, q);
p = q;
} else {
len++;
p++;
}
first = 0;
}
return len;
}
/*}}}*/
static char *append_home_dir(char *to)/*{{{*/
{
struct passwd *foo;
int len;
foo = getpwuid(getuid());
len = strlen(foo->pw_dir);
strcpy(to, foo->pw_dir);
return to + len;
}
/*}}}*/
static char *append_env(char *to, const char *p, const char *q)/*{{{*/
{
char *foo;
int len;
foo = env_lookup(p, q);
if (foo) {
len = strlen(foo);
strcpy(to, foo);
free(foo);
} else {
len = 0;
}
return (to + len);
}
/*}}}*/
static void do_expand(const char *p, char *result)/*{{{*/
{
const char *q;
int first;
first = 1;
while (*p) {
if (first && (*p == '~') && (p[1] == '/')) {
result = append_home_dir(result);
p++;
} else if ((*p == '$') && (p[1] == '{')) {
p += 2;
q = p;
while (*q && (*q != '}')) q++;
result = append_env(result, p, q);
p = *q ? (q + 1) : q;
} else if (*p == '$') {
p++;
q = p;
while (*q && isenv(*(unsigned char*)q)) q++;
result = append_env(result, p, q);
p = q;
} else {
*result++ = *p++;
}
first = 0;
}
*result = 0;
}
/*}}}*/
char *expand_string(const char *p)/*{{{*/
{
/* Return a copy of p, but with
~ expanded to the user's home directory
$env expanded to the value of that environment variable
*/
int len;
char *result;
len = compute_length(p);
result = new_array(char, len+1);
do_expand(p, result);
return result;
}
/*}}}*/
......@@ -97,6 +97,22 @@ BLOCK date
<zone:in->out> ; WHITE -> after_timezone
<zone:in->out> ; WHITE -> after_timezone_1
# It appears that Pine puts the timezone after the year
DIGIT ; DIGIT ; DIGIT ; DIGIT -> after_year_before_zone
STATE after_year_before_zone
WHITE -> after_year_before_zone
<zone:in->out> -> after_timezone_after_year
<zone:in->out> ; WHITE -> after_timezone_after_year_1
STATE after_timezone_after_year_1
WHITE -> after_timezone_after_year_1
<zone:in->out> -> after_timezone_after_year
STATE after_timezone_after_year
WHITE -> after_timezone_after_year
-> out
STATE after_timezone_1
WHITE -> after_timezone_1
<zone:in->out> ; WHITE -> after_timezone
......
......@@ -57,10 +57,12 @@ static int file_exists(char *name)/*{{{*/
static char *copy_value(char *text)/*{{{*/
{
char *p;
char *result;
for (p = text; *p && (*p != '='); p++) ;
if (!*p) return NULL;
p++;
return new_string(p);
result = expand_string(p);
return result;
}
/*}}}*/
static void add_folders(char **folders, char *extra_folders)/*{{{*/
......
......@@ -314,4 +314,7 @@ int scan_date_string(char *in, time_t *start, int *has_start, time_t *end, int *
/* In dumper.c */
void dump_database(char *filename);
/* In strexpand.c */
char *expand_string(const char *p);
#endif /* MAIRIX_H */
......@@ -240,6 +240,8 @@ hierarchy, for example.
@node mairixrc
@section The @file{~/.mairixrc} file
@subsection Overview
This file contains information about where you keep your mail folders, where
you want the index file to be stored and where you want the match folder to
be, into which the search mode places the symlinks.
......@@ -266,6 +268,7 @@ mformat=maildir
database=/home/richard/.mairix_database
@end example
@subsection mairixrc file keys
The keys are as follows:
@table @asis
......@@ -426,6 +429,49 @@ before proceeding. If any duplicates are found (arising from the same folder
being specified twice), it will give an error message and exit. This is to
prevent corrupting the index database file.
@subsection mairixrc expansions
The part of each line in @file{.mairixrc} following the equals sign can contain
the following types of expansion:
@table @asis
@item Home directory expansion
If the sequence @samp{~/} appears at the start of the text after the equals
sign, it is expanded to the user's home directory. Example:
@example
database=~/Mail/mairix_database
@end example
@item Environment expansion
If a @samp{$} is followed by a sequence of alpha-numeric characters (or
@samp{_}), the whole string is replaced by looking up the corresponding
environment variable. Similarly, if @samp{$} is followed by an open brace
(@samp{@{}), everything up to the next close brace is looked up as an
environment variable and the result replaces the entire sequence.
Suppose in the shell we do
@example
export FOO=bar
@end example
and the @file{.mairixrc} file contains
@example
maildir=xxx/$FOO
mbox=yyy/a$@{FOO@}b
@end example
this is equivalent to
@example
maildir=xxx/bar
mbox=yyy/abarb
@end example
If the specified environment variable is not set, the replacement is the empty
string.
@end table
@node mfolder_setup
@section Setting up the match folder
If the match folder does not exist when running in search mode, it is
......
......@@ -979,12 +979,12 @@ struct rfc822 *make_rfc822(char *filename)/*{{{*/
{
/* Now process the data */
result = data_to_rfc822(data, len);
if (munmap(data, (size_t) len) < 0) {
perror("Could not munmap");
}
}
if (munmap(data, (size_t) len) < 0) {
perror("Could not munmap");
}
return result;
}
/*}}}*/
......
......@@ -568,7 +568,7 @@ static void append_file_to_mbox(const char *path, FILE *out)/*{{{*/
int len;
create_ro_mapping(path, &data, &len);
if (data) {
fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n");
fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n");
fwrite (data, sizeof(unsigned char), len, out);
munmap(data, len);
}
......@@ -617,7 +617,7 @@ static void append_mboxmsg_to_mbox(struct read_db *db, int msg_index, FILE *out)
get_validated_mbox_msg(db, msg_index, &mbox_index, &mbox_start, &mbox_len, &msg_start, &msg_len);
if (msg_start) {
fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n");
fprintf(out, "From mairix@mairix Mon Jan 1 12:34:56 1970\n");
fwrite(msg_start, sizeof(unsigned char), msg_len, out);
}
if (mbox_start) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment