home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / lib / alias.c next >
Encoding:
C/C++ Source or Header  |  1994-04-13  |  7.3 KB  |  382 lines

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