home *** CD-ROM | disk | FTP | other *** search
- /*
- * ALIAS.C
- *
- * *MUST* be compiled with 32-bit ints.
- *
- * (C) Copyright 1989-1990 by Matthew Dillon, All Rights Reserved.
- *
- * Interpret UULIB:Aliases file. To save space we do not load
- * the entire file, just sections on demand.
- *
- * # = comment
- * id: name [, name...]
- *
- * name is a user name, path, or |filter, or quoted name. Example,
- * "|more" or "|rnews"
- */
-
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include "config.h"
-
- #include "log.h"
-
- #define HASHSIZE 256
- #define HASHMASK (HASHSIZE-1)
-
- #define HF_TERM 0x01 /* terminator name */
- #define HF_ALIAS 0x02 /* alias */
- #define HF_LOADED 0x04 /* def loaded */
- #define HF_NOEXPAND 0x08 /* do not expand alias */
-
- typedef struct Hash {
- struct Hash *Next;
- short NumAlias; /* # of aliases */
- short Flags;
- char *Name; /* aliased user name */
- union {
- struct Hash **Alias; /* list of aliases */
- long Offset; /* offset into file */
- } u;
- } Hash;
-
- Prototype void LoadAliases (void);
- Prototype int UserAliasList (const char *, int (*)(const char *, struct List *, int), struct List *, int);
- Prototype int AliasExists (const char *);
-
- static Hash *FindHashObject (const char *);
- static void LoadHashObject (Hash *);
- static int HashFunc (const char *);
-
- static Hash
- *HashTab [HASHSIZE];
- static char
- Tmp[256];
-
- void
- LoadAliases (void)
- {
- char
- *buf = Tmp,
- *filename = MakeConfigPath (UULIB, "Aliases");
- FILE
- *fi = fopen (filename, "r");
- int
- i,
- j,
- k,
- line = 0,
- newoffset = 0,
- offset;
- Hash
- *h;
-
- if (fi == NULL) {
- ulog (-1, "Can't open %s", filename);
- return;
- }
-
- while (fgets (buf, 256, fi)) {
- offset = newoffset;
- newoffset = ftell (fi);
- ++line;
- for (i = 0; buf [i] == ' ' || buf [i] == '\t'; ++i)
- ;
- if (buf [i] == '#' || buf [i] == '\n')
- continue;
- for (j = i; buf [j] && buf [j] != ':'; ++j)
- ;
- if (buf [j] == 0) {
- ulog (-1, "No Colon on %s line %d", filename, line);
- continue;
- }
- buf [j] = 0;
-
- k = HashFunc (buf + i);
- h = malloc (sizeof (Hash));
- if (!h) {
- ulog (-1, "No memory for aliases in LoadAliases!");
- continue;
- }
- h->Next = HashTab [k];
- h->NumAlias = 0;
- h->Flags = HF_ALIAS;
- h->Name = malloc (strlen (buf + i) + 1);
- if (!h->Name) {
- ulog (-1, "No memory for alias names in LoadAliases!");
- free (h);
- continue;
- }
- if (buf [j + 1] == ':') {
- h->Flags |= HF_NOEXPAND;
- ++j;
- }
- h->u.Offset = offset + j + 1;
- strcpy (h->Name, buf + i);
-
- HashTab [k] = h;
-
- /*
- * if trailing comma, list continues onto next line
- */
-
- for (;;) {
- for (++j; buf [j]; ++j)
- ;
- while (buf [j - 1] == ' ' ||
- buf [j - 1] == '\t' ||
- buf [j - 1] == '\n') {
- --j;
- }
- if (buf [j - 1] != ',')
- break;
- if (fgets (buf, 256, fi) == NULL)
- break;
- newoffset = ftell (fi);
- j = 0;
- }
- }
-
- fclose (fi);
-
- return;
- }
-
- static Hash *
- FindHashObject (const char *name)
- {
- int
- k = HashFunc (name);
- Hash
- *h;
-
- for (h = HashTab [k]; h; h = h->Next) {
- if (stricmp ((char *) name, h->Name) == 0)
- return h;
- }
-
- return NULL;
- }
-
- static void
- LoadHashObject (Hash *hash)
- {
- char
- *filename = MakeConfigPath (UULIB, "Aliases"),
- *buf = Tmp;
- FILE
- *fi = fopen (filename, "r");
- int
- i,
- j,
- c,
- numalloc = 4;
- Hash
- **hv = malloc (sizeof (Hash *) * 4),
- *h;
-
- if (fi == NULL) {
- ulog (-1, "Can't open %s", filename);
- return;
- }
-
- if (!hv) {
- ulog (-1, "No memory for hash vector in LoadHashObject");
- fclose (fi);
- return;
- }
-
- hash->Flags |= HF_LOADED;
- fseek (fi, hash->u.Offset, 0);
-
- while (fgets (buf, 256, fi)) {
- i = 0;
- c = 'x';
-
- for (i = 0; buf[i] == ' ' || buf[i] == '\t'; ++i)
- ;
- if (buf [i] == '#')
- continue;
-
- for (;;) {
- while (buf [i] == ' ' || buf [i] == '\t')
- ++i;
- if (buf [i] == 0 || buf [i] == '\n' || buf [i] == '#')
- break;
-
- for (j = i; buf [j] != '\n' && buf [j] != ' ' && buf [j] != '\t' && buf [j] != ','; ++j) {
-
- if (buf [j] == '\"') {
- i = j + 1;
-
- for (++j; buf [j] != '\n' && buf [j] != '\"'; ++j) {
- /* allow embedded, escaped quotes */
- if (buf [j] == '\\') {
- buf [j++] = ' ';
- }
- }
-
- break;
- }
- }
- c = buf [j];
- buf [j] = 0;
-
- /*
- * skip remaining junk before comma
- */
-
- while (c && c != '\n' && c != ',')
- c = buf [++j];
-
- if ((h = FindHashObject (buf + i)) == NULL) {
- int
- k = HashFunc (buf + i);
-
- h = malloc (sizeof (Hash));
- if (!h) {
- ulog (-1, "Can't malloc Hash in LoadHashObject");
- break;
- }
- h->Next = HashTab [k];
- h->NumAlias = 0;
- h->Flags = HF_TERM;
- h->Name = malloc (strlen (buf + i) + 1);
- if (!h->Name) {
- ulog (-1, "Can't malloc Hash name in LoadHashObject");
- free (h);
- break;
- }
- h->u.Alias = NULL;
- strcpy (h->Name, buf + i);
-
- HashTab [k] = h;
- }
-
- if (hash->NumAlias == numalloc) {
- Hash
- **hvo = hv;
- int
- add = 4;
-
- hv = malloc (sizeof (Hash *) * (numalloc + add));
- if (!hv) {
- ulog (-1, "Can't malloc expanded hash vector in LoadHashObject");
- break;
- }
- movmem ((char *) hvo, (char *) hv, sizeof (Hash *) * numalloc);
- numalloc += add;
- }
- hv [hash->NumAlias++] = h;
-
- if (c == '\n' || c == 0)
- i = j;
- else
- i = j + 1;
- }
- if (c != ',')
- break;
- }
-
- hash->u.Alias = hv;
-
- return;
- }
-
- int
- AliasExists (const char *user)
- {
- if (FindHashObject (user))
- return 1;
-
- return 0;
- }
-
- /*
- * UserAliasList returns whether the 'user' should be displayed in the
- * To: field of the letter. Normally it isn't, but if an alias is
- * specified to NOT expand on the To: field then the alias name itself
- * IS put on the To: field.
- *
- * showto is passed from an upper level. If set, the callback specifies
- * expansion (unless overriden by the alias), else the callback specifies
- * no expansion.
- *
- * In the case where a high level alias is expanded but a low level alias
- * is not, the callback function is called for the low level alias with
- * a showto of -1, indicating that it should be placed on the To: list
- * WITHOUT being placed on the actual send-to list (because its expansion
- * is passed normally)
- */
-
- int
- UserAliasList (const char *user, int (*callback)(const char *, struct List *, int),
- struct List *arg, int showto)
- {
- int
- i;
- Hash
- *hash = FindHashObject (user);
- static int
- stack;
-
- if (!hash) {
- (*callback) (user, arg, showto);
- return 0;
- }
-
- if (++stack == 32) {
- ulog (-1, "%s recursion near user %s", MakeConfigPath (UULIB, "Aliases"), user);
- --stack;
- return 0;
- }
-
- if ((hash->Flags & HF_TERM) == 0) {
- if ((hash->Flags & HF_LOADED) == 0)
- LoadHashObject (hash);
-
- for (i = 0; i < hash->NumAlias; ++i) {
- Hash
- *h = hash->u.Alias [i];
- int
- r;
-
- if (showto)
- r = UserAliasList (h->Name, callback, arg, !(hash->Flags & HF_NOEXPAND));
- else
- r = UserAliasList (h->Name, callback, arg, 0);
- --stack;
- if (r && showto && !(hash->Flags & HF_NOEXPAND))
- (*callback) (h->Name, arg, -1);
- }
- }
- else {
- if (showto)
- (*callback) (user, arg, !(hash->Flags & HF_NOEXPAND));
- else
- (*callback) (user, arg, 0);
- }
-
- --stack;
-
- if (hash->Flags & HF_NOEXPAND)
- return 1;
-
- return 0;
- }
-
- static int
- HashFunc (const char *str)
- {
- unsigned long
- v = 0x14FBA5C3;
-
- while (*str) {
- v = (v << 5) ^ (*str & 0x1F) ^ (v >> 27);
- ++str;
- }
- return (int) (v & HASHMASK);
- }
-