home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / lib / alias.c next >
C/C++ Source or Header  |  1990-12-27  |  7KB  |  301 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.  
  47. Local Hash *FindHashObject(const char *);
  48. Local void LoadHashObject(Hash *);
  49. Local int  HashFunc(const char *);
  50.  
  51. static Hash    *HashTab[HASHSIZE];
  52. static char    Tmp[256];
  53.  
  54. void
  55. LoadAliases()
  56. {
  57.     FILE *fi = fopen(MakeConfigPath(UULIB, "Aliases"), "r");
  58.     short i;
  59.     short j;
  60.     short k;
  61.     short line = 0;
  62.     long newoffset = 0;
  63.     long offset;
  64.     Hash *h;
  65.     char *buf = Tmp;
  66.  
  67.     if (fi == NULL) {
  68.     strcpy(buf, MakeConfigPath(UULIB, "Aliases"));
  69.     ulog(-1, "Can't open %s", buf);
  70.     return;
  71.     }
  72.     while (fgets(buf, 256, fi)) {
  73.     offset = newoffset;
  74.     newoffset = ftell(fi);
  75.     ++line;
  76.     for (i = 0; buf[i] == ' ' || buf[i] == 9; ++i);
  77.     if (buf[i] == '#' || buf[i] == '\n')
  78.         continue;
  79.     for (j = i; buf[j] && buf[j] != ':'; ++j);
  80.     if (buf[j] == 0) {
  81.         strcpy(buf, MakeConfigPath(UULIB, "Aliases"));
  82.         ulog(-1, "No Colon %s line %d", buf, line);
  83.         continue;
  84.     }
  85.     buf[j] = 0;
  86.  
  87.     k = HashFunc(buf + i);
  88.     h = malloc(sizeof(Hash));
  89.     h->Next = HashTab[k];
  90.     h->NumAlias = 0;
  91.     h->Flags = HF_ALIAS;
  92.     h->Name = malloc(strlen(buf+i) + 1);
  93.     if (buf[j+1] == ':') {
  94.         h->Flags |= HF_NOEXPAND;
  95.         ++j;
  96.     }
  97.     h->u.Offset = offset + j + 1;
  98.     strcpy(h->Name, buf + i);
  99.  
  100.     HashTab[k] = h;
  101.  
  102.     /*
  103.      *  if trailing comma, list continues onto next line
  104.      */
  105.  
  106.     for (;;) {
  107.         for (++j; buf[j]; ++j);
  108.         while (buf[j-1] == ' ' || buf[j-1] == 9 || buf[j-1] == '\n')
  109.         --j;
  110.         if (buf[j-1] != ',')
  111.         break;
  112.         if (fgets(buf, 256, fi) == NULL)
  113.         break;
  114.         newoffset = ftell(fi);
  115.         j = 0;
  116.     }
  117.     }
  118.     fclose(fi);
  119. }
  120.  
  121. static
  122. Hash *
  123. FindHashObject(name)
  124. const char *name;
  125. {
  126.     short k = HashFunc(name);
  127.     Hash *h;
  128.  
  129.     for (h = HashTab[k]; h; h = h->Next) {
  130.     if (strcmp(name, h->Name) == 0)
  131.         return(h);
  132.     }
  133.     return(NULL);
  134. }
  135.  
  136. static
  137. void
  138. LoadHashObject(hash)
  139. Hash *hash;
  140. {
  141.     FILE *fi = fopen(MakeConfigPath(UULIB, "Aliases"), "r");
  142.     char *buf = Tmp;
  143.     short i, j;
  144.     short c;
  145.     short numalloc = 4;
  146.     Hash **hv = malloc(sizeof(Hash *) * 4);
  147.     Hash *h;
  148.  
  149.     if (fi == NULL) {
  150.     ulog(-1, "Can't open %s", MakeConfigPath(UULIB, "Aliases"));
  151.     return;
  152.     }
  153.  
  154.     hash->Flags |= HF_LOADED;
  155.     fseek(fi, hash->u.Offset, 0);
  156.  
  157.     while (fgets(buf, 256, fi)) {
  158.     i = 0;
  159.     c = 'x';
  160.  
  161.     for (i = 0; buf[i] == ' ' || buf[i] == 9; ++i);
  162.     if (buf[i] == '#')
  163.         continue;
  164.  
  165.     for (;;) {
  166.         while (buf[i] == ' ' || buf[i] == 9)
  167.         ++i;
  168.         if (buf[i] == 0 || buf[i] == '\n' || buf[i] == '#')
  169.         break;
  170.  
  171.         for (j = i; buf[j] != '\n' && buf[j] != ' ' && buf[j] != 9 && buf[j] != ','; ++j) {
  172.         if (buf[j] == '\"') {
  173.             i = j + 1;
  174.             for (++j; buf[j] != '\n' && buf[j] != '\"'; ++j);
  175.             break;
  176.         }
  177.         }
  178.         c = buf[j];
  179.         buf[j] = 0;
  180.  
  181.         /*
  182.          *    skip remaining junk before comma
  183.          */
  184.  
  185.         while (c && c != '\n' && c != ',')
  186.         c = buf[++j];
  187.  
  188.         if ((h = FindHashObject(buf + i)) == NULL) {
  189.         short k = HashFunc(buf + i);
  190.  
  191.         h = malloc(sizeof(Hash));
  192.         h->Next = HashTab[k];
  193.         h->NumAlias = 0;
  194.         h->Flags = HF_TERM;
  195.         h->Name = malloc(strlen(buf + i) + 1);
  196.         h->u.Alias = NULL;
  197.         strcpy(h->Name, buf + i);
  198.  
  199.         HashTab[k] = h;
  200.         }
  201.  
  202.         if (hash->NumAlias == numalloc) {
  203.         Hash **hvo = hv;
  204.         short add = 4;
  205.  
  206.         hv = malloc(sizeof(Hash *) * (numalloc + add));
  207.         movmem((char *)hvo, (char *)hv, sizeof(Hash *) * numalloc);
  208.         numalloc += add;
  209.         }
  210.         hv[hash->NumAlias++] = h;
  211.  
  212.         if (c == '\n' || c == 0)
  213.         i = j;
  214.         else
  215.         i = j + 1;
  216.     }
  217.     if (c != ',')
  218.         break;
  219.     }
  220.     hash->u.Alias = hv;
  221. }
  222.  
  223. /*
  224.  *  UserAliasList returns whether the 'user' should be displayed in the
  225.  *  To: field of the letter.  Normally it isn't, but if an alias is
  226.  *  specified to NOT expand on the To: field then the alias name itself
  227.  *  IS put on the To: field.
  228.  *
  229.  *  showto is passed from an upper level.  If set, the callback specifies
  230.  *  expansion (unless overriden by the alias), else the callback specifies
  231.  *  no expansion.
  232.  *
  233.  *  In the case where a high level alias is expanded but a low level alias
  234.  *  is not, the callback function is called for the low level alias with
  235.  *  a showto of -1, indicating that it should be placed on the To: list
  236.  *  WITHOUT being placed on the actual send-to list (because its expansion
  237.  *  is passed normally)
  238.  */
  239.  
  240. int
  241. UserAliasList(user, callback, arg, showto)
  242. const char *user;
  243. int (*callback)(const char *, long, int);
  244. long arg;
  245. int showto;
  246. {
  247.     short i;
  248.     int r;
  249.     Hash *hash = FindHashObject(user);
  250.     static short stack;
  251.  
  252.     if (++stack == 32) {
  253.     ulog(-1, "%s recursion near user %s", MakeConfigPath(UULIB, "Aliases"), user);
  254.     --stack;
  255.     return;
  256.     }
  257.  
  258.     if (hash) {
  259.     if ((hash->Flags & HF_TERM) == 0) {
  260.         if ((hash->Flags & HF_LOADED) == 0)
  261.         LoadHashObject(hash);
  262.         for (i = 0; i < hash->NumAlias; ++i) {
  263.         Hash *h = hash->u.Alias[i];
  264.         int r;
  265.  
  266.         if (showto)
  267.             r = UserAliasList(h->Name, callback, arg, !(hash->Flags & HF_NOEXPAND));
  268.         else
  269.             r = UserAliasList(h->Name, callback, arg, 0);
  270.         --stack;
  271.         if (r && showto && !(hash->Flags & HF_NOEXPAND))
  272.             (*callback)(h->Name, arg, -1);
  273.         }
  274.     } else {
  275.         if (showto)
  276.         (*callback)(user, arg, !(hash->Flags & HF_NOEXPAND));
  277.         else
  278.         (*callback)(user, arg, 0);
  279.     }
  280.     } else {
  281.     (*callback)(user, arg, showto);
  282.     }
  283.     --stack;
  284.     if (hash && (hash->Flags & HF_NOEXPAND))
  285.     return(1);
  286.     return(0);
  287. }
  288.  
  289. static int
  290. HashFunc(str)
  291. const char *str;
  292. {
  293.     unsigned long v = 0x14FBA5C3;
  294.     while (*str) {
  295.     v = (v << 5) ^ (*str & 0x1F) ^ (v >> 27);
  296.     ++str;
  297.     }
  298.     return((int)(v & HASHMASK));
  299. }
  300.  
  301.