static char rcsid[] = "@(#)$Id: aliasdb.c,v 1.10 2006/04/09 07:37:05 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.10 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
/** Alias interface with dbz routines.
This code is shared with newalias and elm so that
it is easier to do updates while in elm. The routines in
this file are interface routines between elm alias code,
newalias, and listalias and the dbm routines.
**/
#include "headers.h"
#include "ndbz.h"
#ifdef BSD_TYPE
# include <sys/file.h>
#endif
/* byte-ordering stuff */
#define MAPIN(o) ((db->dbz_bytesame) ? (of_t) (o) : bytemap((of_t)(o), db->dbz_conf.bytemap, db->dbz_mybmap))
#define MAPOUT(o) ((db->dbz_bytesame) ? (of_t) (o) : bytemap((of_t)(o), db->dbz_mybmap, db->dbz_conf.bytemap))
static of_t bytemap P_((of_t ino,
int *map1,
int *map2));
static of_t /* transformed result */
bytemap(ino, map1, map2)
of_t ino;
int *map1;
int *map2;
{
union oc {
of_t o;
char c[SOF];
};
union oc in;
union oc out;
register int i;
in.o = ino;
for (i = 0; i < SOF; i++)
out.c[map2[i]] = in.c[map1[i]];
return(out.o);
}
int read_one_alias P_((DBZ *db,
struct alias_disk_rec *adr));
int read_one_alias(db, adr)
DBZ *db;
struct alias_disk_rec *adr;
{
/*
* Read an alias (name, address, etc.) from the data file
*/
FILE *data_file = db->dbz_basef;
if (data_file == NULL)
return(0); /* no alias file, but hash exists, error condition */
if (fread((char *) adr, sizeof(struct alias_disk_rec), 1, data_file)
<= 0)
return(0);
adr->status = (int32) MAPIN(adr->status);
adr->alias = (int32) MAPIN(adr->alias);
adr->last_name = (int32) MAPIN(adr->last_name);
adr->name = (int32) MAPIN(adr->name);
adr->comment = (int32) MAPIN(adr->comment);
adr->address = (int32) MAPIN(adr->address);
adr->type = (int32) MAPIN(adr->type);
adr->length = (int32) MAPIN(adr->length);
return(1);
}
/*
* Retrieve an alias record and information from a database.
*
* If "alias" is non-NULL, it is the name of the alias to fetch (searching
* is case insensitive). If the alias is found, we return a pointer to
* dynamically allocated memory that holds an alias record *plus* the
* text data for that record. If the lookup fails or an error occurs,
* then a NULL is returned.
*
* If "alias" is NULL then the next alias in the database is retrieved.
* This may be used to scan through the database. Again, a pointer to
* dynamically allocated memory is returned. When the end of file is
* reached, a NULL is returned.
*/
struct alias_rec *fetch_alias(db, alias)
DBZ *db;
char *alias;
{
datum key, val;
struct alias_disk_rec adrec;
long pos;
register struct alias_rec *ar;
register char *buf, *s;
/*
* If an alias is specifed then locate it.
*/
if (alias != NULL) {
/*
* Fetch location of this alias.
*/
key.dptr = safe_strdup(alias);
for (s = key.dptr ; *s != '\0' ; ++s) {
if (isascii(*s))
*s = tolower(*s);
}
key.dsize = strlen(alias);
val = dbz_fetch(db, key);
(void) free((malloc_t)key.dptr);
/*
* Make sure the alias was found.
*/
if (val.dptr == NULL)
return (struct alias_rec *)NULL;
/*
* Sanity check - return value should be a seek offset.
*/
if (val.dsize != sizeof(long))
return (struct alias_rec *)NULL;
/*
* Move to the position of the selected alias record.
*/
pos = *((long *)(val.dptr)) - sizeof(struct alias_disk_rec);
if (fseek(db->dbz_basef, pos, SEEK_SET) != 0)
return (struct alias_rec *)NULL;
}
/*
* Each alias in the data file is stored as a (struct alias_rec)
* followed by text information for that alias record. The
* size of the following text information is specified by `length',
* and the value of the other members of the structure are actually
* offsets into that buffer space. So, to load in an alias we
* need to: (1) read the alias record, (2) see how long the data
* buffer is and pull it in, and (3) fixup the pointers in the
* alias record so they point into the data buffer.
*/
/*
* We are now positioned at the alias record we want. Pull it in.
*/
if (!read_one_alias(db, &adrec))
return (struct alias_rec *)NULL;
/*
* Allocate space to hold the alias record and data content.
*/
ar = (struct alias_rec *)
safe_malloc(sizeof(struct alias_rec) + (size_t)adrec.length);
buf = (char *)ar + sizeof(struct alias_rec);
/*
* Fixup pointers in the alias record.
*/
ar->status = (int)adrec.status;
ar->alias = (char *) ((size_t) adrec.alias + (size_t) buf);
ar->last_name = (char *) ((size_t) adrec.last_name + (size_t) buf);
ar->name = (char *) ((size_t) adrec.name + (size_t) buf);
ar->comment = (char *) ((size_t) adrec.comment + (size_t) buf);
ar->address = (char *) ((size_t) adrec.address + (size_t) buf);
ar->type = (int)adrec.type;
ar->length = (size_t)adrec.length;
/*
* Read in the data content
*/
if (fread(buf, ar->length, 1, db->dbz_basef) != 1)
return (struct alias_rec *)NULL;
return ar;
}
/*
* Return a pointer to the next address in this list, and update the pointer
* to the list. Addresses are seperated by whitespace and/or commas.
* Return NULL when list finished. This routine scribbles on the list.
*/
char *next_addr_in_list(aptr)
char **aptr;
{
register char *front, *back;
/*
* Locate the first letter of the address.
*/
front = *aptr;
while (*front == ',' || isspace(*front))
++front;
if (*front == '\0')
return (char *) NULL;
/*
* Locate the end of the address.
*/
back = front;
while (*back != '\0' && *back != ',' && !isspace(*back))
++back;
if (*back != '\0')
*back++ = '\0';
*aptr = back;
return front;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1