home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / uucp / amigauucpsrc / lib / alias.c next >
C/C++ Source or Header  |  1994-06-29  |  7KB  |  311 lines

  1.  
  2. /*
  3.  *  ALIAS.C
  4.  *
  5.  *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
  6.  *
  7.  *  Interpret UULIB:Aliases file.  To save space we do not load
  8.  *  the entire file, just sections on demand.
  9.  *
  10.  *  #    = comment
  11.  *  id: name [, name...]
  12.  *
  13.  *  name is a user name, path, or |filter, or quoted name.  Example,
  14.  *  "|more" or "|rnews"
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <fcntl.h>
  20. #include <time.h>
  21. #include "config.h"
  22.  
  23. #include "log.h"
  24.  
  25. #define HASHSIZE    256
  26. #define HASHMASK    (HASHSIZE-1)
  27.  
  28. #define HF_TERM     0x01    /*    terminator name     */
  29. #define HF_ALIAS    0x02    /*    alias            */
  30. #define HF_LOADED   0x04    /*    def loaded        */
  31. #define HF_NOEXPAND 0x08    /*    do not expand alias    */
  32.  
  33. typedef struct Hash {
  34.     struct Hash *Next;
  35.     short   NumAlias;    /*  # of aliases    */
  36.     short   Flags;
  37.     char    *Name;    /*  aliased user name    */
  38.     union {
  39.     struct Hash    **Alias;    /*  list of aliases       */
  40.     long    Offset;     /*    offset into file    */
  41.     } u;
  42. } Hash;
  43.  
  44. Prototype void LoadAliases(void);
  45. Prototype int  UserAliasList(const char *, int (*)(const char *, long, int), long, int);
  46. Prototype int  AliasExists(const char *);
  47.  
  48. Local Hash *FindHashObject(const char *);
  49. Local void LoadHashObject(Hash *);
  50. Local int  HashFunc(const char *);
  51.  
  52. static Hash    *HashTab[HASHSIZE];
  53. static char    Tmp[256];
  54.  
  55. void
  56. LoadAliases()
  57. {
  58.     FILE *fi = fopen(MakeConfigPath(UULIB, "Aliases"), "r");
  59.     short i;
  60.     short j;
  61.     short k;
  62.     short line = 0;
  63.     long newoffset = 0;
  64.     long offset;
  65.     Hash *h;
  66.     char *buf = Tmp;
  67.  
  68.     if (fi == NULL) {
  69.     strcpy(buf, MakeConfigPath(UULIB, "Aliases"));
  70.     ulog(-1, "Can't open %s", buf);
  71.     return;
  72.     }
  73.     while (fgets(buf, 256, fi)) {
  74.     offset = newoffset;
  75.     newoffset = ftell(fi);
  76.     ++line;
  77.     for (i = 0; buf[i] == ' ' || buf[i] == 9; ++i);
  78.     if (buf[i] == '#' || buf[i] == '\n')
  79.         continue;
  80.     for (j = i; buf[j] && buf[j] != ':'; ++j);
  81.     if (buf[j] == 0) {
  82.         strcpy(buf, MakeConfigPath(UULIB, "Aliases"));
  83.         ulog(-1, "No Colon %s line %d", buf, line);
  84.         continue;
  85.     }
  86.     buf[j] = 0;
  87.  
  88.     k = HashFunc(buf + i);
  89.     h = malloc(sizeof(Hash));
  90.     h->Next = HashTab[k];
  91.     h->NumAlias = 0;
  92.     h->Flags = HF_ALIAS;
  93.     h->Name = malloc(strlen(buf+i) + 1);
  94.     if (buf[j+1] == ':') {
  95.         h->Flags |= HF_NOEXPAND;
  96.         ++j;
  97.     }
  98.     h->u.Offset = offset + j + 1;
  99.     strcpy(h->Name, buf + i);
  100.  
  101.     HashTab[k] = h;
  102.  
  103.     /*
  104.      *  if trailing comma, list continues onto next line
  105.      */
  106.  
  107.     for (;;) {
  108.         for (++j; buf[j]; ++j);
  109.         while (buf[j-1] == ' ' || buf[j-1] == 9 || buf[j-1] == '\n')
  110.         --j;
  111.         if (buf[j-1] != ',')
  112.         break;
  113.         if (fgets(buf, 256, fi) == NULL)
  114.         break;
  115.         newoffset = ftell(fi);
  116.         j = 0;
  117.     }
  118.     }
  119.     fclose(fi);
  120. }
  121.  
  122. static
  123. Hash *
  124. FindHashObject(name)
  125. const char *name;
  126. {
  127.     short k = HashFunc(name);
  128.     Hash *h;
  129.  
  130.     for (h = HashTab[k]; h; h = h->Next) {
  131.     if (stricmp(name, h->Name) == 0)
  132.         return(h);
  133.     }
  134.     return(NULL);
  135. }
  136.  
  137. static
  138. void
  139. LoadHashObject(hash)
  140. Hash *hash;
  141. {
  142.     FILE *fi = fopen(MakeConfigPath(UULIB, "Aliases"), "r");
  143.     char *buf = Tmp;
  144.     short i, j;
  145.     short c;
  146.     short numalloc = 4;
  147.     Hash **hv = malloc(sizeof(Hash *) * 4);
  148.     Hash *h;
  149.  
  150.     if (fi == NULL) {
  151.     ulog(-1, "Can't open %s", MakeConfigPath(UULIB, "Aliases"));
  152.     return;
  153.     }
  154.  
  155.     hash->Flags |= HF_LOADED;
  156.     fseek(fi, hash->u.Offset, 0);
  157.  
  158.     while (fgets(buf, 256, fi)) {
  159.     i = 0;
  160.     c = 'x';
  161.  
  162.     for (i = 0; buf[i] == ' ' || buf[i] == 9; ++i);
  163.     if (buf[i] == '#')
  164.         continue;
  165.  
  166.     for (;;) {
  167.         while (buf[i] == ' ' || buf[i] == 9)
  168.         ++i;
  169.         if (buf[i] == 0 || buf[i] == '\n' || buf[i] == '#')
  170.         break;
  171.  
  172.         for (j = i; buf[j] != '\n' && buf[j] != ' ' && buf[j] != 9 && buf[j] != ','; ++j) {
  173.         if (buf[j] == '\"') {
  174.             i = j + 1;
  175.             for (++j; buf[j] != '\n' && buf[j] != '\"'; ++j);
  176.             break;
  177.         }
  178.         }
  179.         c = buf[j];
  180.         buf[j] = 0;
  181.  
  182.         /*
  183.          *    skip remaining junk before comma
  184.          */
  185.  
  186.         while (c && c != '\n' && c != ',')
  187.         c = buf[++j];
  188.  
  189.         if ((h = FindHashObject(buf + i)) == NULL) {
  190.         short k = HashFunc(buf + i);
  191.  
  192.         h = malloc(sizeof(Hash));
  193.         h->Next = HashTab[k];
  194.         h->NumAlias = 0;
  195.         h->Flags = HF_TERM;
  196.         h->Name = malloc(strlen(buf + i) + 1);
  197.         h->u.Alias = NULL;
  198.         strcpy(h->Name, buf + i);
  199.  
  200.         HashTab[k] = h;
  201.         }
  202.  
  203.         if (hash->NumAlias == numalloc) {
  204.         Hash **hvo = hv;
  205.         short add = 4;
  206.  
  207.         hv = malloc(sizeof(Hash *) * (numalloc + add));
  208.         movmem((char *)hvo, (char *)hv, sizeof(Hash *) * numalloc);
  209.         numalloc += add;
  210.         }
  211.         hv[hash->NumAlias++] = h;
  212.  
  213.         if (c == '\n' || c == 0)
  214.         i = j;
  215.         else
  216.         i = j + 1;
  217.     }
  218.     if (c != ',')
  219.         break;
  220.     }
  221.     hash->u.Alias = hv;
  222. }
  223.  
  224. int
  225. AliasExists(user)
  226. const char *user;
  227. {
  228.     if (FindHashObject(user))
  229.     return(1);
  230.     return(0);
  231. }
  232.  
  233. /*
  234.  *  UserAliasList returns whether the 'user' should be displayed in the
  235.  *  To: field of the letter.  Normally it isn't, but if an alias is
  236.  *  specified to NOT expand on the To: field then the alias name itself
  237.  *  IS put on the To: field.
  238.  *
  239.  *  showto is passed from an upper level.  If set, the callback specifies
  240.  *  expansion (unless overriden by the alias), else the callback specifies
  241.  *  no expansion.
  242.  *
  243.  *  In the case where a high level alias is expanded but a low level alias
  244.  *  is not, the callback function is called for the low level alias with
  245.  *  a showto of -1, indicating that it should be placed on the To: list
  246.  *  WITHOUT being placed on the actual send-to list (because its expansion
  247.  *  is passed normally)
  248.  */
  249.  
  250. int
  251. UserAliasList(user, callback, arg, showto)
  252. const char *user;
  253. int (*callback)(const char *, long, int);
  254. long arg;
  255. int showto;
  256. {
  257.     short i;
  258.     int r;
  259.     Hash *hash = FindHashObject(user);
  260.     static short stack;
  261.  
  262.     if (++stack == 32) {
  263.     ulog(-1, "%s recursion near user %s", MakeConfigPath(UULIB, "Aliases"), user);
  264.     --stack;
  265.     return;
  266.     }
  267.  
  268.     if (hash) {
  269.     if ((hash->Flags & HF_TERM) == 0) {
  270.         if ((hash->Flags & HF_LOADED) == 0)
  271.         LoadHashObject(hash);
  272.         for (i = 0; i < hash->NumAlias; ++i) {
  273.         Hash *h = hash->u.Alias[i];
  274.         int r;
  275.  
  276.         if (showto)
  277.             r = UserAliasList(h->Name, callback, arg, !(hash->Flags & HF_NOEXPAND));
  278.         else
  279.             r = UserAliasList(h->Name, callback, arg, 0);
  280.         --stack;
  281.         if (r && showto && !(hash->Flags & HF_NOEXPAND))
  282.             (*callback)(h->Name, arg, -1);
  283.         }
  284.     } else {
  285.         if (showto)
  286.         (*callback)(user, arg, !(hash->Flags & HF_NOEXPAND));
  287.         else
  288.         (*callback)(user, arg, 0);
  289.     }
  290.     } else {
  291.     (*callback)(user, arg, showto);
  292.     }
  293.     --stack;
  294.     if (hash && (hash->Flags & HF_NOEXPAND))
  295.     return(1);
  296.     return(0);
  297. }
  298.  
  299. static int
  300. HashFunc(str)
  301. const char *str;
  302. {
  303.     unsigned long v = 0x14FBA5C3;
  304.     while (*str) {
  305.     v = (v << 5) ^ (*str & 0x1F) ^ (v >> 27);
  306.     ++str;
  307.     }
  308.     return((int)(v & HASHMASK));
  309. }
  310.  
  311.