[EXIM] formated hash function

Startseite
Nachricht löschen
Nachricht beantworten
Autor: yann.golanski
Datum:  
To: EXIM users list
Betreff: [EXIM] formated hash function
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 */