/* * $Filename: expandalias $ * $Revision: 1.11 $ * $Date: 1994/03/13 18:24:34 $ * * Copyright (C) 1993 by Peter Simons * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: expandalias.c,v 1.11 1994/03/13 18:24:34 simons Exp simons $ * */ /************************************************************************** * * * Sektion: Macros, Definitions, Includes, Structures * * * **************************************************************************/ /************************************* Includes ***********/ #include #include #include #include #include #include #include #include "protos.h" /************************************* Defines ************/ #define MAX_RECEIPIENTS 1024 /* * max. number of receipients */ #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; /************************************* Prototypes *********/ static void callBack(char *, long, int); static Hash *FindHashObject(const char *); static void LoadHashObject(Hash *); static int HashFunc(const char *); /************************************* global Variables ***/ static const char __RCSId[] = "$Id: expandalias.c,v 1.11 1994/03/13 18:24:34 simons Exp simons $"; static char **new_receipients; static Hash *HashTab[HASHSIZE]; static char Tmp[256]; /************************************************************************** * * * Sektion: Unterprogramme * * * **************************************************************************/ char **ExpandAliases(char *receipients[]) { char **new_receipients2; if (*receipients == NULL) return NULL; if ((new_receipients = malloc(sizeof(char *[MAX_RECEIPIENTS]))) == NULL) return NULL; new_receipients2 = new_receipients; LoadAliases(); while (*receipients != NULL) { UserAliasList(*receipients, (int (*)(char *, long, int)) callBack, 0L, 1); receipients++; } *new_receipients = NULL; return new_receipients2; } static void callBack(char *name, long dummy, int show) { switch (name[0]) { case '|': case '>': case '<': break; case '\\': ++name; default: *new_receipients = name; new_receipients++; break; } } void LoadAliases(void) { FILE *fi = fopen("UULib:Aliases", "r"); short i, j, k, line = 0; long offset, newoffset = 0; Hash *h; char *buf = Tmp; if (fi == NULL) { MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Can't open UULib:Aliases!"); return; } while (fgets(buf, 256, fi)) { offset = newoffset; newoffset = ftell(fi); ++line; for (i = 0; buf[i] == ' ' || buf[i] == 9; ++i) ; if (buf[i] == '#' || buf[i] == '\n') continue; for (j = i; buf[j] && buf[j] != ':'; ++j) ; if (buf[j] == 0) { MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "No Colon UULib:Aliases line %d.", line); continue; } buf[j] = 0; k = HashFunc(buf + i); h = malloc(sizeof(Hash)); h->Next = HashTab[k]; h->NumAlias = 0; h->Flags = HF_ALIAS; h->Name = malloc(strlen(buf + i) + 1); 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] == 9 || buf[j - 1] == '\n') --j; if (buf[j - 1] != ',') break; if (fgets(buf, 256, fi) == NULL) break; newoffset = ftell(fi); j = 0; } } fclose(fi); } static Hash *FindHashObject(const char *name) { short k = HashFunc(name); Hash *h; for (h = HashTab[k]; h; h = h->Next) { if (stricmp(name, h->Name) == 0) return (h); } return (NULL); } static void LoadHashObject(Hash * hash) { FILE *fi = fopen("UUlib:Aliases", "r"); char *buf = Tmp; short i, j; short c; short numalloc = 4; Hash **hv = malloc(sizeof(Hash *) * 4); Hash *h; if (fi == NULL) { MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "Can't open UULib:Aliases!"); 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] == 9; ++i) ; if (buf[i] == '#') continue; for (;;) { while (buf[i] == ' ' || buf[i] == 9) ++i; if (buf[i] == 0 || buf[i] == '\n' || buf[i] == '#') break; for (j = i; buf[j] != '\n' && buf[j] != ' ' && buf[j] != 9 && buf[j] != ','; ++j) { if (buf[j] == '\"') { i = j + 1; for (++j; buf[j] != '\n' && buf[j] != '\"'; ++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) { short k = HashFunc(buf + i); h = malloc(sizeof(Hash)); h->Next = HashTab[k]; h->NumAlias = 0; h->Flags = HF_TERM; h->Name = malloc(strlen(buf + i) + 1); h->u.Alias = NULL; strcpy(h->Name, buf + i); HashTab[k] = h; } if (hash->NumAlias == numalloc) { Hash **hvo = hv; short add = 4; hv = malloc(sizeof(Hash *) * (numalloc + add)); 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; } 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 *, long, int), long arg, int showto) { short i; Hash *hash = FindHashObject(user); static short stack; if (++stack == 32) { MakeLogEntry(PRGNAME, MLE_FATAL_ERROR, "UULib:Aliases recursion near user %s.", user); --stack; return 0; } if (hash) { 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); } } else { (*callback) (user, arg, showto); } --stack; if (hash && (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)); }