This is a patch to exim-3.02 that adds one function to the expand.c
routines.
The function is a `formated hash' (fh) that takes a number of options:
${formatedhash_retval_sept_hrange_str}
where
retval is an int, defining the number of output returned. Should be
smaller than 100.
sept is a list of characters, separated by `;', that will be used
to separate the hashed part.
hrange is a list of ints, separated by `;', that is the range of
the hash.
str is the string that will be hashed.
For example:
${local_part} = fred@???
/var/spool/${formatedhash_3_/;/;/_10;20;30_${local_part}}/Mailbox
would return 3 hash numbers based on ${local_part} separated by `/'. The
first hashed number returned would be mapped from 0 to 9, the second from 0
to 19 and the third from 0 to 29. The returned line would look like:
/var/spool/7/17/27/Mailbox
Here is a small list of other example, without the text:
/var/spool/${formatedhash_1_/_1000_${local_part}}/ ==> /var/spool/417/
/var/spool/${formatedhash_2_/;M_5496;5_${local_part}}/ ==> /var/spool/417/2M/
Comments and criticisms are of course welcome.
--
Yann Golanski Internet Systems Developer
yann.golanski@??? The Planet Online
*** expand.c.orig Wed Jun 2 09:31:53 1999
--- expand.c Mon Jun 21 15:34:22 1999
***************
*** 968,974 ****
quote quote the argument if it contains anything other
than letters, digits, underscores, dots, & hyphens;
quoting means putting inside "" and \-quoting any
! \ or " in the string
rxquote regular expression quote: any non-alphameric is
quoted with \
substr_<m>_<n> substring n chars from offset m
--- 968,974 ----
quote quote the argument if it contains anything other
than letters, digits, underscores, dots, & hyphens;
quoting means putting inside "" and \-quoting any
! \ or '"' in the string
rxquote regular expression quote: any non-alphameric is
quoted with \
substr_<m>_<n> substring n chars from offset m
***************
*** 1033,1039 ****
--- 1033,1041 ----
{
char *value;
char name[256];
+
+
/* \ escapes the next character, which must exist, or else
the expansion fails. */
***************
*** 1601,1606 ****
--- 1603,1609 ----
}
#endif /* EXIM_PERL */
+
/* Handle keyed and numbered substring extraction. They are distinguised
by different numbers of arguments. */
***************
*** 1653,1660 ****
continue;
}
! /* Handle operations on a subsequent string */
if (*s == ':')
{
char *sub = expand_string_internal(s+1, TRUE, &s, FALSE);
--- 1656,1807 ----
continue;
}
! /* Planet superhash function */
! /*
! fh_retval_sept_hrange_str
! returns a foirmated hash. Usefull for directory structures.
! where
! retval is an int.
! sept is a list of chars
! hrange is a list of ints
! str is the string you want to hash
!
! lists have to be separated by ";"
! */
!
! if ( strncmp(name, "formatedhash_", 12) == 0
! || strncmp(name, "fh_", 3) == 0
! )
! {
! const char delim1 = '_';
! const char delim2 = ';';
! static char option[256], str[256], retstr[256], matrix[256], sept[100];
! static char *tmp, *tmp_retval, *tmp_sept, *tmp_hrange, *tmp_str;
! static unsigned int i, len, retval;
! static unsigned int hrange[100], hashval[100];
!
! char *sub = expand_string_internal(s+1, TRUE, &s, FALSE);
! if (sub == NULL) goto EXPAND_FAILED;
! s++;
!
!
! /* copy the option string */
! strcpy(matrix, string);
! fprintf(stderr, "full line = %s\n", matrix);
! tmp = strchr(matrix, '_' ) +1 ;
! strcpy(option, tmp);
! fprintf(stderr, "working line = %s\n", option);
!
! /* splits from option line the retval option and checks for sanity */
! if ( !(tmp_retval = strtok(option, &delim1)) ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: retval is NULL" ,string);
! goto EXPAND_FAILED;
! }
!
! /* splits from option line the separators option and checks for sanity */
! if ( !(tmp_sept = strtok(NULL, &delim1)) ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: sept is NULL" ,string);
! goto EXPAND_FAILED;
! }
!
! /* splits from option line the hrange values option and checks for sanity */
! if ( !(tmp_hrange = strtok(NULL, &delim1)) ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: hrange is NULL" ,string);
! goto EXPAND_FAILED;
! }
!
! /* splits from option line the the string to hash option and checks for sanity */
! if ( !(tmp_str = strtok(NULL, &delim1)) ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: str is NULL" ,string);
! goto EXPAND_FAILED;
! }
!
! /* gets the values from the string */
! if ( isdigit( *tmp_retval ) ) {
! retval = atoi( tmp_retval );
! if ( retval > 100 ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: retval (= %d)is way too big" ,retval, string);
! goto EXPAND_FAILED;
! }
! } else {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: retval is NaN" ,string);
! goto EXPAND_FAILED;
! }
!
! /* gets the values from the string */
! sept[0] = *strtok( tmp_sept, &delim2 );
! for ( i = 1; i < retval; i++ ) {
! tmp = strtok(NULL, &delim2);
! if ( !tmp ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: Not enough values for sept!" ,string);
! goto EXPAND_FAILED;
! }
! sept[i] = *tmp;
! }
!
! /* gets the values from the string */
! if ( isdigit( *tmp_hrange ) ) {
! hrange[0] = atoi( strtok( tmp_hrange, &delim2 ) );
! } else {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: hrange is NaN!" ,string);
! goto EXPAND_FAILED;
! }
! for ( i = 1; i < retval; i++ ) {
! tmp = strtok(NULL, &delim2);
! if ( !tmp ) {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: Not enough values for hrange!" ,string);
! goto EXPAND_FAILED;
! }
! if ( isdigit( *tmp ) ) {
! hrange[i] = atoi( tmp );
! } else {
! expand_string_message =
! string_sprintf("internal expansion of \"%s\" failed: hrange is NaN!" ,string);
! goto EXPAND_FAILED;
! }
! }
+ /* start of hashing string */
+ strcpy(str, tmp_str);
+ for ( i = 0; i < retval; i++ ) {
+ static unsigned int total;
+ for ( total = 0, tmp = str; *tmp != '}'; tmp++ ) {
+ if ( *tmp == '\n' || *tmp == '\0') break;
+ total += (unsigned int)(*tmp);
+ /*printf(" CHAR = \"%c\"\n", *tmp);*/
+ }
+ hashval[i] = total % hrange[i];
+ }
+
+ for ( *retstr = '\0', i = 0; i < retval; i++ ) {
+ sprintf(retstr, "%s%d%c", retstr, hashval[i], sept[i] );
+ }
+
+ printf("ret string = %s\n", retstr);
+ fprintf(stderr,"%d -->", retval);
+ for ( i = 0; i < retval; i++ )
+ fprintf(stderr,"%c %d", sept[i], hrange[i]);
+ fprintf(stderr, "\n");
+
+ yield = string_cat(yield, &size, &ptr, retstr, (int)strlen(retstr));
+ s++;
+ continue;
+ }
+ /* end of superhash */
+
+
+
+
+ /* Handle operations on a subsequent string */
if (*s == ':')
{
char *sub = expand_string_internal(s+1, TRUE, &s, FALSE);
***************
*** 1894,1899 ****
--- 2041,2048 ----
}
continue;
}
+
+
/* Unknown operator */