824N/A/*
943N/A * Copyright (c) 1993, 1996, Oracle and/or its affiliates. All rights reserved.
824N/A *
824N/A * Permission is hereby granted, free of charge, to any person obtaining a
919N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
919N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
919N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
824N/A */
824N/A
824N/A
824N/A#include <stdio.h>
824N/A#include <stdlib.h>
824N/A#include <sys/types.h>
824N/A#include <sys/stat.h>
824N/A#include <fcntl.h>
824N/A#include <ctype.h>
824N/A#include <unistd.h>
824N/A#include <string.h>
824N/A#include <errno.h>
824N/A#include "Sunowconfig.h"
824N/A
824N/A/***************************************************************************
824N/AImplementation Note: This implementation was done with some generality
824N/A in mind. If at some point it becomes necessary to add more
824N/A elaborate per class or per instance data, this should be
824N/A readily accommodated by this implementation.
824N/A
824N/A It is assumed that the configuration database is relatively
824N/A small, say, fewer than 1000 entries. There's no hard limit, but
824N/A there's no optimization either.
824N/A
824N/A The "package" mechanism is hokey. It was done to
824N/A address the concern that nobody wanted package names specified
824N/A on a per instance basis, but there needed to be some mechanism
824N/A that identified an instance as belonging to a package.
824N/A
824N/A The previous implementation mentioned that it was not
824N/A MTsafe or MThot. The same applies to this implementation.
824N/A
824N/A Error handling is very primitive. If a more sophisticated
824N/A means of reporting and acting upon error conditions can be
824N/A developed..., great.
824N/A
824N/A It would be nice if we could use alloca, but since this
824N/A is also an Xsun server library, we can't.
824N/A***************************************************************************/
824N/A
824N/A/***************************************************************************
824N/A OWconfig implementation private data structures...
824N/A***************************************************************************/
824N/A
824N/Astruct databaseStruct {
824N/A int dummy;
824N/A};
824N/A
824N/Astruct classStruct {
824N/A int dummy;
824N/A};
824N/A
824N/Astruct instanceStruct {
824N/A char *pkg;
824N/A int lineNumber;
824N/A struct nodeStruct *nextInstance, *prevInstance;
824N/A};
824N/A
824N/Astruct attrStruct {
824N/A char *value;
824N/A};
824N/A
824N/A/*
824N/A * A class list is a child of the database.
824N/A * An instance list is a child of a class.
824N/A * An attribute list is a child of an instance.
824N/A */
824N/Astruct nodeStruct {
824N/A char *name;
824N/A unsigned int hashValue;
824N/A struct nodeStruct *next;
824N/A struct nodeStruct *prev;
824N/A struct nodeStruct *parent;
824N/A struct nodeStruct *head; /* One end of the child list... */
824N/A struct nodeStruct *tail; /* The other end... */
824N/A void (*nodeFree)();
824N/A union {
824N/A struct databaseStruct database;
824N/A struct classStruct class;
824N/A struct instanceStruct instance;
824N/A struct attrStruct attr;
824N/A } nodeValue;
824N/A};
824N/A
824N/A
824N/A
824N/A/*
824N/A * Store comments as a singly linked list...
824N/A */
824N/Astruct commentStruct {
824N/A char *comment;
824N/A int lineNumber;
824N/A struct commentStruct *next;
824N/A};
824N/A
824N/A
824N/A/*** Max pathname length... ***/
824N/A#define FNLENGTH 300
824N/A
824N/A/*** Unit of allocation for input line buffer... ***/
824N/A
824N/A#define LINEALLOCUNIT 128
824N/A
824N/A/*** Max length of statically allocated strings... ***/
824N/A#define MAXVALLENGTH 128
824N/A
824N/A
824N/A/***************************************************************************
824N/AData Declarations...
824N/A***************************************************************************/
824N/Astatic struct nodeStruct OWconfigDatabase;
824N/Astatic int databaseValid = 0;
824N/A
824N/Astatic char currentPackage[MAXVALLENGTH];
824N/Astatic char *defaultNewPkgName="RESERVED-unassigned";
824N/Astatic char *defaultOldPkgName="RESERVED-oldstyle";
824N/A
824N/A/*** If ever there are multiple databases, this could be moved into
824N/A a database nodeStruct.
824N/A***/
824N/Astatic char *readFile1 = NULL;
824N/Astatic char *readFile2 = NULL;
824N/Astatic int OWconfigFlags = 0;
824N/Astatic void *(*allocMem)();
824N/Astatic void (*freeMem)();
824N/Astatic time_t readFile1TimeStamp;
824N/Astatic time_t readFile2TimeStamp;
824N/Astatic struct commentStruct *commentList = NULL;
824N/Astatic struct commentStruct *lastComment = NULL;
824N/Astatic struct nodeStruct *instanceListHead = NULL;
824N/Astatic struct nodeStruct *instanceListTail = NULL;
824N/Astatic int lineNumber;
824N/Astatic int lastLineNumber;
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/A****************************************************************************
824N/AImplementation private functions...
824N/A****************************************************************************
824N/A***************************************************************************/
824N/A
824N/A#define FREENODE(np) \
824N/A if (np->parent->head == np)\
824N/A np->parent->head = np->next;\
824N/A if (np->parent->tail == np)\
824N/A np->parent->tail = np->prev;\
824N/A if (np->next)\
824N/A np->next->prev = np->prev;\
824N/A if (np->prev)\
824N/A np->prev->next = np->next;\
824N/A freeMem(np->name);\
824N/A freeMem((char *)np);
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AfreeNodeList: The generic node list destructor...
824N/A***************************************************************************/
824N/Astatic void
824N/AfreeNodeList(struct nodeStruct *np)
824N/A{
824N/A struct nodeStruct *next;
824N/A
824N/A while (np) {
824N/A if (np->head)
824N/A freeNodeList(np->head);
824N/A next = np->next;
824N/A if (np->nodeFree)
824N/A np->nodeFree(np);
824N/A np = next;
824N/A }
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AfreeClass: The class node destructor...
824N/A***************************************************************************/
824N/Astatic void
824N/AfreeClass(struct nodeStruct *cp)
824N/A{
824N/A if (cp->head)
824N/A freeNodeList(cp->head);
824N/A
824N/A FREENODE(cp);
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AfreeInstance: The instance node destructor...
824N/A***************************************************************************/
824N/Astatic void
824N/AfreeInstance(struct nodeStruct *ip)
824N/A{
824N/A char *tmp;
824N/A struct nodeStruct *nextInstance, *prevInstance;
824N/A
824N/A if (ip->head)
824N/A freeNodeList(ip->head);
824N/A
824N/A tmp = ip->nodeValue.instance.pkg;
824N/A if (tmp)
824N/A freeMem(tmp);
824N/A
824N/A if (OWconfigFlags & OWFLAG_RETAIN) {
824N/A nextInstance = ip->nodeValue.instance.nextInstance;
824N/A prevInstance = ip->nodeValue.instance.prevInstance;
824N/A if (nextInstance)
824N/A nextInstance->nodeValue.instance.prevInstance =
824N/A prevInstance;
824N/A if (prevInstance)
824N/A prevInstance->nodeValue.instance.nextInstance =
824N/A nextInstance;
824N/A if (instanceListHead == ip)
824N/A instanceListHead = nextInstance;
824N/A if (instanceListTail == ip)
824N/A instanceListTail = prevInstance;
824N/A }
824N/A
824N/A FREENODE(ip);
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AfreeAttr: The attribute node destructor...
824N/A***************************************************************************/
824N/Astatic void
824N/AfreeAttr(struct nodeStruct *ap)
824N/A{
824N/A char *value;
824N/A
824N/A value = ap->nodeValue.attr.value;
824N/A if (value)
824N/A freeMem(value);
824N/A
824N/A FREENODE(ap);
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AhashValue: Generates the arithmetic sum of the bytes of the string
824N/A specified by "str".
824N/A***************************************************************************/
824N/Astatic unsigned int
824N/AhashValue(char *str)
824N/A{
824N/A unsigned int ret = 0;
824N/A
824N/A while (*str) {
824N/A ret += (unsigned int)*str;
824N/A str++;
824N/A }
824N/A
824N/A return(ret);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AdupString: Given a non-null pointer to a string, allocates memory
824N/A sufficient to contain a copy of the string pointed to by
824N/A "str", copies the string to the newly allocated memory, and
824N/A returns a pointer to the new string.
824N/A***************************************************************************/
824N/Astatic char *
824N/AdupString(char *str)
824N/A{
824N/A int len;
824N/A char *ptr;
824N/A
824N/A if (str) {
824N/A len = strlen(str) + 1;
824N/A
824N/A ptr = (char *)allocMem(len);
824N/A if (ptr)
824N/A (void)memcpy(ptr, str, len);
824N/A
824N/A return(ptr);
824N/A } else
824N/A return(NULL);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AsearchNodeList: Searches next-wise along a list, starting at the node
824N/A pointed to by "node", until either the end of the list is
824N/A found, or a node whose name matches the string pointed to by
824N/A "name".
824N/A***************************************************************************/
824N/Astatic struct nodeStruct *
824N/AsearchNodeList(struct nodeStruct *node, char *name)
824N/A{
824N/A unsigned int nameHash;
824N/A
824N/A nameHash = hashValue(name);
824N/A while (node) {
824N/A if ((nameHash == node->hashValue) && !strcmp(name, node->name))
824N/A break;
824N/A node = node->next;
824N/A }
824N/A
824N/A return(node);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AsearchClass: Searches for the class node whose name matches the string
824N/A pointed to by "class".
824N/A***************************************************************************/
824N/Astatic struct nodeStruct *
824N/AsearchClass(char *class)
824N/A{
824N/A if (OWconfigDatabase.head)
824N/A return(searchNodeList(OWconfigDatabase.head, class));
824N/A
824N/A return((struct nodeStruct *)NULL);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AsearchInstance: Searches for the instance node identified by "name",
824N/A parented by the class node identified by "class".
824N/A***************************************************************************/
824N/Astatic struct nodeStruct *
824N/AsearchInstance(char *class, char *name)
824N/A{
824N/A struct nodeStruct *cp;
824N/A
824N/A cp = searchClass(class);
824N/A if (cp && cp->head)
824N/A return(searchNodeList(cp->head, name));
824N/A
824N/A return((struct nodeStruct *)NULL);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AsearchAttr: Searches for the attribute node identified by "attr",
824N/A parented by the instance node identified by "name",
824N/A which in turn is parented by the class node identified by "class".
824N/A***************************************************************************/
824N/Astatic struct nodeStruct *
824N/AsearchAttr(char *class, char *name, char *attr)
824N/A{
824N/A struct nodeStruct *instanceNode;
824N/A
824N/A instanceNode = searchInstance(class, name);
824N/A if (instanceNode && instanceNode->head)
824N/A return(searchNodeList(instanceNode->head, attr));
824N/A
824N/A return((struct nodeStruct *)NULL);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AcreateClass: Creates a new class node within the OWconfig database.
824N/A***************************************************************************/
824N/Astatic struct nodeStruct *
824N/AcreateClass(char *class)
824N/A{
824N/A struct nodeStruct *cp;
824N/A
824N/A cp = (struct nodeStruct *)allocMem(sizeof(struct nodeStruct));
824N/A if (!cp)
824N/A return(NULL);
824N/A cp->name = dupString(class);
824N/A if (!cp->name) {
824N/A freeMem(cp);
824N/A return(NULL);
824N/A }
824N/A cp->hashValue = hashValue(class);
824N/A cp->parent = &OWconfigDatabase;
824N/A cp->head = NULL;
824N/A cp->tail = NULL;
824N/A cp->nodeFree = freeClass;
824N/A
824N/A if (!OWconfigDatabase.head) {
824N/A OWconfigDatabase.head = cp;
824N/A }
824N/A
824N/A cp->prev = OWconfigDatabase.tail;
824N/A cp->next = NULL;
824N/A
824N/A if (OWconfigDatabase.tail)
824N/A OWconfigDatabase.tail->next = cp;
824N/A
824N/A OWconfigDatabase.tail = cp;
824N/A
824N/A return(cp);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AcreateInstance: Creates a new instance node parented by the class node
824N/A identified by "class". The instance node will be identified
824N/A by "name". If the class node does not already exist, it will
824N/A be created.
824N/A***************************************************************************/
824N/Astatic struct nodeStruct *
824N/AcreateInstance(char *class, char *name)
824N/A{
824N/A struct nodeStruct *cp, *ip;
824N/A
824N/A cp = searchClass(class);
824N/A if (!cp) {
824N/A cp = createClass(class);
824N/A if (!cp) {
824N/A return(NULL);
824N/A }
824N/A }
824N/A ip = (struct nodeStruct *)allocMem(sizeof(struct nodeStruct));
824N/A if (!ip)
824N/A return(NULL);
824N/A ip->name = dupString(name);
824N/A if (!ip->name) {
824N/A freeMem(ip);
824N/A return(NULL);
824N/A }
824N/A ip->hashValue = hashValue(name);
824N/A ip->parent = cp;
824N/A ip->head = NULL;
824N/A ip->tail = NULL;
824N/A ip->nodeFree = freeInstance;
824N/A ip->nodeValue.instance.pkg = NULL;
824N/A
824N/A if (OWconfigFlags & OWFLAG_RETAIN) {
824N/A if (instanceListTail) {
824N/A if (instanceListTail->nodeValue.instance.lineNumber ==
824N/A lineNumber)
824N/A lineNumber++;
824N/A ip->nodeValue.instance.lineNumber = lineNumber;
824N/A ip->nodeValue.instance.nextInstance = NULL;
824N/A ip->nodeValue.instance.prevInstance = instanceListTail;
824N/A instanceListTail->nodeValue.instance.nextInstance = ip;
824N/A instanceListTail = ip;
824N/A } else {
824N/A instanceListHead = instanceListTail = ip;
824N/A ip->nodeValue.instance.lineNumber = lineNumber;
824N/A ip->nodeValue.instance.nextInstance = NULL;
824N/A ip->nodeValue.instance.prevInstance = NULL;;
824N/A }
824N/A }
824N/A
824N/A if (!cp->head) {
824N/A cp->head = ip;
824N/A }
824N/A
824N/A ip->prev = cp->tail;
824N/A ip->next = NULL;
824N/A
824N/A if (cp->tail)
824N/A cp->tail->next = ip;
824N/A
824N/A cp->tail = ip;
824N/A
824N/A return(ip);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AunlockOWconfig: Remove the read or write lock from an OWconfig file.
824N/A***************************************************************************/
824N/Astatic void
824N/AunlockOWconfig(int f)
824N/A{
824N/A/* 4007038
824N/ARemvoe any read/write locking/unlocking.
824N/A flock_t lockStruct;
824N/A
824N/A lockStruct.l_type = F_UNLCK;
824N/A lockStruct.l_whence = 0;
824N/A lockStruct.l_start = 0;
824N/A lockStruct.l_len = 0;
824N/A (void)fcntl(f, F_SETLK, &lockStruct);
824N/A*/
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AreadLockOWconfig: Place a read lock on an OWconfig file. Should only
824N/A fail if the file is write locked.
824N/A***************************************************************************/
824N/Astatic int
824N/AreadLockOWconfig(int f)
824N/A{
824N/A/* 4007038
824N/ADo not do any read locking.
824N/A
824N/A int result;
824N/A flock_t lockStruct;
824N/A
824N/A lockStruct.l_type = F_RDLCK;
824N/A lockStruct.l_whence = 0;
824N/A lockStruct.l_start = 0;
824N/A lockStruct.l_len = 0;
824N/A result = fcntl(f, F_SETLK, &lockStruct);
824N/A if (result != -1)
824N/A return(OWCFG_OK);
824N/A else
824N/A return(OWCFG_LOCK1FAIL);
824N/A*/
824N/A return(OWCFG_OK);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AwriteLockOWconfig: Place a write lock on an OWconfig file. Will fail
824N/A if any other locks, read or write, are already on the file.
824N/A***************************************************************************/
824N/Astatic int
824N/AwriteLockOWconfig(int f)
824N/A{
824N/A/* 4007038
824N/ADo not do any write locking.
824N/A
824N/A int result;
824N/A flock_t lockStruct;
824N/A
824N/A lockStruct.l_type = F_WRLCK;
824N/A lockStruct.l_whence = 0;
824N/A lockStruct.l_start = 0;
824N/A lockStruct.l_len = 0;
824N/A result = fcntl(f, F_SETLK, &lockStruct);
824N/A if (result != -1)
824N/A return(OWCFG_OK);
824N/A else
824N/A return(OWCFG_LOCK1FAIL);
824N/A*/
824N/A return(OWCFG_OK);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AaccumulateComment:
824N/A***************************************************************************/
824N/Astatic void
824N/AaccumulateComment(char *comment, int lineNumber)
824N/A{
824N/A int len;
824N/A struct commentStruct *newComment;
824N/A
824N/A len = strlen(comment);
824N/A if (len == 0)
824N/A return;
824N/A
824N/A if (*comment =='\n')
824N/A return;
824N/A
824N/A newComment = (struct commentStruct *)
824N/A allocMem(len + 1 + sizeof(struct commentStruct));
824N/A newComment->comment = (char *)newComment +
824N/A sizeof(struct commentStruct);
824N/A strcpy(newComment->comment, comment);
824N/A newComment->lineNumber = lineNumber;
824N/A newComment->next = NULL;
824N/A if (lastComment != NULL) {
824N/A lastComment->next = newComment;
824N/A lastComment = newComment;
824N/A } else {
824N/A commentList = lastComment = newComment;
824N/A }
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AfreeComments:
824N/A***************************************************************************/
824N/Astatic void
824N/AfreeComments(void)
824N/A{
824N/A struct commentStruct *commentP = commentList;
824N/A struct commentStruct *next;
824N/A
824N/A while (commentP) {
824N/A next = commentP->next;
824N/A freeMem(commentP);
824N/A commentP = next;
824N/A }
824N/A
824N/A commentList = NULL;
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AinitDatabase: If a database already exists, free it, and set the
824N/A OWconfigDatabase structure to a known state.
824N/A***************************************************************************/
824N/Astatic void
824N/AinitDatabase(void)
824N/A{
824N/A if (databaseValid) {
824N/A freeNodeList(OWconfigDatabase.head);
824N/A freeMem(readFile1);
824N/A readFile1 = NULL;
824N/A freeMem(readFile2);
824N/A readFile2 = NULL;
824N/A freeComments();
824N/A }
824N/A
824N/A databaseValid = 1;
824N/A OWconfigDatabase.head = NULL;
824N/A OWconfigDatabase.tail = NULL;
824N/A OWconfigDatabase.next = NULL;
824N/A OWconfigDatabase.prev = NULL;
824N/A OWconfigDatabase.nodeFree = (void (*)())0;
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AreAllocMem: Because we don't really want to add another parameter to
824N/A OWconfigInit..., we implement a realloc routine that uses
824N/A the allocMem and freeMem routines specified by OWconfigInit.
824N/A***************************************************************************/
824N/Astatic char *
824N/AreAllocMem(char *ptr, unsigned int oldSize, unsigned int newSize)
824N/A{
824N/A char *newPtr;
824N/A
824N/A if (newSize <= oldSize)
824N/A return(ptr);
824N/A
824N/A newPtr = allocMem(newSize);
824N/A if (newPtr) {
824N/A memcpy(newPtr, ptr, oldSize);
824N/A freeMem(ptr);
824N/A }
824N/A
824N/A return(newPtr);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AreadLine: Read the file, line by line, until an "interesting" line
824N/A is encountered. Maintain a line number counter along the
824N/A way. When a line is found, fill "lineBuf" with the data.
824N/A It is the responsibility of the caller to free the dynamically
824N/A allocated line buffer.
824N/ANote: Need to find proper way to use ctype functions...
824N/A***************************************************************************/
824N/Astatic int
824N/AreadLine(FILE *fp, char **lineBuf, int *lineNumber)
824N/A{
824N/A char *result;
824N/A int lineBufSize = LINEALLOCUNIT+1;
824N/A
824N/A (*lineNumber)++;
824N/A
824N/A *lineBuf = (char *)allocMem(lineBufSize);
824N/A if (!*lineBuf)
824N/A return(EOF);
824N/A
824N/A result = fgets(*lineBuf, LINEALLOCUNIT, fp);
824N/A
824N/A if (result) {
824N/A int bufLen = strlen(result);
824N/A
824N/A while (result[bufLen-1] != 0xa) {
824N/A char *newBuf;
824N/A int newBufSize;
824N/A
824N/A newBufSize = lineBufSize + LINEALLOCUNIT;
824N/A newBuf = reAllocMem(*lineBuf, lineBufSize, newBufSize);
824N/A
824N/A if (!newBuf) {
824N/A freeMem(*lineBuf);
824N/A *lineBuf = NULL;
824N/A return(EOF);
824N/A }
824N/A
824N/A *lineBuf = newBuf;
824N/A lineBufSize = newBufSize;
824N/A result = fgets((newBuf)+bufLen,
824N/A LINEALLOCUNIT, fp);
824N/A
824N/A if (!result) {
824N/A freeMem(*lineBuf);
824N/A *lineBuf = NULL;
824N/A return(EOF);
824N/A }
824N/A
824N/A bufLen = strlen(newBuf);
824N/A result = newBuf;
824N/A }
824N/A
824N/A while (isspace(*result) && *result != '#' && *result)
824N/A result++;
824N/A if (*result == '#' || *result == (char)0) {
824N/A if (OWconfigFlags & OWFLAG_RETAIN) {
824N/A accumulateComment(*lineBuf, *lineNumber);
824N/A }
824N/A freeMem(*lineBuf);
824N/A return(readLine(fp, lineBuf, lineNumber));
824N/A } else
824N/A return(1);
824N/A } else {
824N/A return(EOF);
824N/A }
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AreadPair: Starting at character position "charPos" in "lineBuf",
824N/A search for an expression of appx. the following syntax:
824N/A
824N/A <alnum>{<whitespace>}<equal>{<whitespace>}\
824N/A (<quote><anything goes, even \ stuff><quote>) | \
824N/A <alnum>
824N/A
824N/A If such an expression is found, "nameBuf" is filled with the
824N/A value to the left of the = and "valBuf" is filled with the
824N/A value to the right of the =. "charPos" will be updated to
824N/A point at the next candidate expression.
824N/A***************************************************************************/
824N/Astatic int
824N/AreadPair(char *lineBuf, char *nameBuf, char *valBuf, int *charPos)
824N/A{
824N/A char *ptr = lineBuf + *charPos;
824N/A
824N/A /*** Skip whitespace preceding name... ***/
824N/A while (*ptr && isspace(*ptr))
824N/A ptr++;
824N/A
824N/A if ((!isalnum(*ptr)) || *ptr == (char)0 || *ptr == ';') {
824N/A *charPos = (int)(ptr - lineBuf);
824N/A if (*ptr == (char)0 || *ptr == ';')
824N/A return(!OWCFG_OK);
824N/A else
824N/A return(OWCFG_SYNTAX1);
824N/A }
824N/A
824N/A /*** Get name... ***/
824N/A while (*ptr && isalnum(*ptr)) {
824N/A *nameBuf = *ptr;
824N/A nameBuf++;
824N/A ptr++;
824N/A }
824N/A
824N/A *nameBuf = (char)0;
824N/A
824N/A /*** Skip "=" and whitespace preceding open quote or string...***/
824N/A while (*ptr && (*ptr=='=' || isspace(*ptr)))
824N/A ptr++;
824N/A
824N/A if (*ptr == (char)0) {
824N/A *charPos = (int)(ptr - lineBuf);
824N/A return(OWCFG_SYNTAX1);
824N/A }
824N/A
824N/A if (*ptr == '"') {
824N/A /*** Fetch quote delimited string... ***/
824N/A ptr++;
824N/A while (*ptr && *ptr != '"') {
824N/A if (*ptr == '\\') {
824N/A if (!*(++ptr))
824N/A break;
824N/A }
824N/A *valBuf = *ptr;
824N/A valBuf++;
824N/A ptr++;
824N/A }
824N/A } else {
824N/A /*** Fetch white space terminated string... ***/
824N/A while (*ptr && (*ptr != ';') && (!isspace(*ptr))) {
824N/A if (*ptr == '\\') {
824N/A if (!*(++ptr))
824N/A break;
824N/A }
824N/A *valBuf = *ptr;
824N/A valBuf++;
824N/A ptr++;
824N/A }
824N/A }
824N/A
824N/A *valBuf = (char)0;
824N/A
824N/A /*** Skip past terminating character, if any. ***/
824N/A if (*ptr)
824N/A ptr++;
824N/A
824N/A *charPos = (int)(ptr - lineBuf);
824N/A return(OWCFG_OK);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AreadOWconfig: Read the OWconfig database file named by "fileName".
824N/A The internal database is built and the file's last modified time
824N/A is returned in "timeStamp". If anything goes wrong, it is
824N/A the caller's responsibility to clean up the database.
824N/A***************************************************************************/
824N/Astatic int
824N/AreadOWconfig(char *fileName, time_t *timeStamp)
824N/A{
824N/A char *lineBuf = NULL;
824N/A char nameBuf[MAXVALLENGTH];
824N/A char *valBuf = NULL;
824N/A char classVal[MAXVALLENGTH];
824N/A char nameVal[MAXVALLENGTH];
824N/A char pkgVal[MAXVALLENGTH];
824N/A int skipping = 0;
824N/A FILE *fp;
824N/A struct stat statbuf;
824N/A int result;
824N/A int syntaxResult = OWCFG_OK;
824N/A
824N/A fp = fopen(fileName, "r");
824N/A if (!fp)
824N/A return(OWCFG_OPEN1FAIL);
824N/A if (readLockOWconfig(fileno(fp)) != OWCFG_OK) {
824N/A (void)fclose(fp);
824N/A return(OWCFG_LOCK1FAIL);
824N/A }
824N/A
824N/A classVal[0] = (char)0;
824N/A nameVal[0] = (char)0;
824N/A pkgVal[0] = (char)0;
824N/A
824N/A strcpy(currentPackage, defaultOldPkgName);
824N/A
824N/A while (readLine(fp, &lineBuf, &lineNumber) != EOF) {
824N/A int charPos;
824N/A
824N/A valBuf = allocMem(strlen(lineBuf)+1);
824N/A if (!valBuf) {
824N/A freeMem(lineBuf);
824N/A unlockOWconfig(fileno(fp));
824N/A fclose(fp);
824N/A return(OWCFG_ALLOC);
824N/A }
824N/A
824N/A charPos = 0;
824N/A while ((result = readPair(lineBuf, nameBuf, valBuf,
824N/A &charPos)) == OWCFG_OK)
824N/A {
824N/A /*** class=<value> ??? ***/
824N/A if (!strcmp(nameBuf, "class")) {
824N/A (void)strcpy(classVal, valBuf);
824N/A skipping = 0;
824N/A
824N/A /*** name=<value> ??? ***/
824N/A } else if (!strcmp(nameBuf, "name")) {
824N/A (void)strcpy(nameVal, valBuf);
824N/A skipping = 0;
824N/A
824N/A /*** package=<value> ??? ***/
824N/A } else if (!strcmp(nameBuf, "package")) {
824N/A (void)strcpy(currentPackage, valBuf);
824N/A skipping = 0;
824N/A
824N/A /*** <attr>=<value> ??? ***/
824N/A } else if (*classVal != (char)0 && *nameVal != (char)0) {
824N/A result = OWconfigSetAttribute(classVal, nameVal,
824N/A nameBuf, valBuf);
824N/A if (result != OWCFG_OK) {
824N/A unlockOWconfig(fileno(fp));
824N/A (void)fclose(fp);
824N/A if (lineBuf)
824N/A freeMem(lineBuf);
824N/A if (valBuf)
824N/A freeMem(valBuf);
824N/A return(result);
824N/A }
824N/A skipping = 0;
824N/A
824N/A /*** BLAMMO (TM)... ***/
824N/A } else {
824N/A if (!skipping) {
824N/A (void)fprintf(stderr,"%s\n",lineBuf);
824N/A (void)fprintf(stderr,"^^^ Bad class instance, line %d, ^^^\n", lineNumber-lastLineNumber);
824N/A (void)fprintf(stderr," in file %s.\n", fileName);
824N/A skipping = 1;
824N/A }
824N/A classVal[0] = (char)0;
824N/A nameVal[0] = (char)0;
824N/A }
824N/A
824N/A } /* while readPair... */
824N/A
824N/A if (result == OWCFG_SYNTAX1)
824N/A syntaxResult = result;
824N/A
824N/A if (lineBuf[charPos] == ';') {
824N/A classVal[0] = (char)0;
824N/A nameVal[0] = (char)0;
824N/A }
824N/A
824N/A if (lineBuf) {
824N/A freeMem(lineBuf);
824N/A lineBuf = NULL;
824N/A }
824N/A
824N/A if (valBuf) {
824N/A freeMem(valBuf);
824N/A valBuf = NULL;
824N/A }
824N/A
824N/A
824N/A } /* while readLine... */
824N/A
824N/A if (lineBuf)
824N/A freeMem(lineBuf);
824N/A
824N/A if (valBuf)
824N/A freeMem(valBuf);
824N/A
824N/A (void)fstat(fileno(fp), &statbuf);
824N/A *timeStamp = statbuf.st_mtime;
824N/A
824N/A unlockOWconfig(fileno(fp));
824N/A (void)fclose(fp);
824N/A
824N/A return(syntaxResult);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AwriteString: Writes to "fp" a quoted string specified by "str". Does
824N/A the necessary \ stuff.
824N/A***************************************************************************/
824N/Astatic void
824N/AwriteString(FILE *fp, char *str)
824N/A{
824N/A if (str) {
824N/A (void)fputc('"', fp);
824N/A while (*str) {
824N/A if (*str == '\\' || *str == '"')
824N/A (void)fputc('\\', fp);
824N/A (void)fputc(*str, fp);
824N/A str++;
824N/A }
824N/A (void)fputc('"', fp);
824N/A } else {
824N/A (void)fprintf(fp, "\"\"");
824N/A }
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AwriteDatabase:
824N/A***************************************************************************/
824N/Astatic void
824N/AwriteDatabase(FILE *fp)
824N/A{
824N/A struct nodeStruct *cp, *ip, *ap;
824N/A
824N/A /*** Need to do something about Copyright notices... ***/
824N/A
824N/A currentPackage[0] = (char)0;
824N/A
824N/A if (OWconfigFlags && OWFLAG_RETAIN) {
824N/A struct commentStruct *commentP = commentList;
824N/A
824N/A ip = instanceListHead;
824N/A
824N/A /*** Write database in something resembling
824N/A original source order...
824N/A ***/
824N/A while (ip) {
824N/A char *pkg = ip->nodeValue.instance.pkg;
824N/A
824N/A cp = ip->parent;
824N/A
824N/A while (commentP && (commentP->lineNumber <
824N/A ip->nodeValue.instance.lineNumber))
824N/A {
824N/A (void)fprintf(fp, "%s", commentP->comment);
824N/A commentP = commentP->next;
824N/A }
824N/A
824N/A /*** Start new package? ***/
824N/A if (strcmp(currentPackage, pkg)) {
824N/A (void)strcpy(currentPackage, pkg);
824N/A (void)fprintf(fp, "\npackage=");
824N/A writeString(fp, currentPackage);
824N/A (void)fprintf(fp, "\n\n");
824N/A }
824N/A (void)fprintf(fp, "class=");
824N/A writeString(fp, cp->name);
824N/A (void)fprintf(fp, " ");
824N/A (void)fprintf(fp, "name=");
824N/A writeString(fp, ip->name);
824N/A (void)fprintf(fp, "\n");
824N/A for (ap = ip->head;
824N/A ap;
824N/A ap = ap->next)
824N/A {
824N/A (void)fprintf(fp, " %s=", ap->name);
824N/A writeString(fp, ap->nodeValue.attr.value);
824N/A if (ap->next)
824N/A (void)fprintf(fp, "\n");
824N/A else
824N/A (void)fprintf(fp, ";\n");
824N/A }
824N/A
824N/A ip = ip->nodeValue.instance.nextInstance;
824N/A }
824N/A
824N/A while (commentP) {
824N/A (void)fprintf(fp, "%s", commentP->comment);
824N/A commentP = commentP->next;
824N/A }
824N/A
824N/A } else {
824N/A
824N/A /*** Write database, class by class... ***/
824N/A for (cp = OWconfigDatabase.head;
824N/A cp;
824N/A cp = cp->next)
824N/A {
824N/A for (ip = cp->head;
824N/A ip;
824N/A ip = ip->next)
824N/A {
824N/A char *pkg = ip->nodeValue.instance.pkg;
824N/A
824N/A /*** Start new package? ***/
824N/A if (strcmp(currentPackage, pkg)) {
824N/A (void)strcpy(currentPackage, pkg);
824N/A (void)fprintf(fp, "package=");
824N/A writeString(fp, currentPackage);
824N/A (void)fprintf(fp, "\n\n");
824N/A }
824N/A (void)fprintf(fp, "class=");
824N/A writeString(fp, cp->name);
824N/A (void)fprintf(fp, " ");
824N/A (void)fprintf(fp, "name=");
824N/A writeString(fp, ip->name);
824N/A (void)fprintf(fp, "\n");
824N/A for (ap = ip->head;
824N/A ap;
824N/A ap = ap->next)
824N/A {
824N/A (void)fprintf(fp, " %s=", ap->name);
824N/A writeString(fp, ap->nodeValue.attr.value);
824N/A if (ap->next)
824N/A (void)fprintf(fp, "\n");
824N/A else
824N/A (void)fprintf(fp, ";\n");
824N/A }
824N/A } /* for */
824N/A } /* for */
824N/A }
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AwriteOWconfig: Writes the internal database, in OWconfig syntax, to
824N/A the file specified by fileName. As a precaution, the original
824N/A file is preserved, renamed as <filename>.BAK.
824N/A
824N/ANote: I'm concerned that a more sophisticated locking mechanism might be
824N/Amore trouble prone than this one.
824N/A***************************************************************************/
824N/Astatic int
824N/AwriteOWconfig(char *fileName)
824N/A{
824N/A FILE *fp;
824N/A char tmpFileName[FNLENGTH];
824N/A char bakFileName[FNLENGTH];
824N/A char pidString[FNLENGTH];
824N/A int f;
824N/A
824N/A (void)sprintf(pidString, ".%d", getpid());
824N/A (void)strcpy(tmpFileName, fileName);
824N/A (void)strcat(tmpFileName, pidString);
824N/A (void)strcpy(bakFileName, fileName);
824N/A (void)strcat(bakFileName, ".BAK");
824N/A fp = fopen(tmpFileName, "w");
824N/A if (!fp)
824N/A return(OWCFG_OPENTMPFAIL);
824N/A
824N/A writeDatabase(fp);
824N/A
824N/A (void)fclose(fp);
824N/A
824N/A /*** Try write locking current OWconfig file... ***/
824N/A f = open(fileName, O_WRONLY);
824N/A if (f == -1) {
824N/A if (errno != ENOENT) {
824N/A (void)unlink(tmpFileName);
824N/A return(OWCFG_OPENWFAIL);
824N/A }
824N/A } else {
824N/A if (writeLockOWconfig(f) != OWCFG_OK) {
824N/A (void)close(f);
824N/A (void)unlink(tmpFileName);
824N/A return(OWCFG_LOCKWFAIL);
824N/A }
824N/A if (rename(fileName, bakFileName) == -1) {
824N/A unlockOWconfig(f);
824N/A (void)close(f);
824N/A (void)unlink(tmpFileName);
824N/A return(OWCFG_RENAMEFAIL);
824N/A }
824N/A }
824N/A if (rename(tmpFileName, fileName) == -1) {
824N/A if (f != -1) {
824N/A (void)rename(bakFileName, fileName);
824N/A unlockOWconfig(f);
824N/A (void)close(f);
824N/A }
824N/A (void)unlink(tmpFileName);
824N/A return(OWCFG_RENAMEFAIL);
824N/A }
824N/A
824N/A unlockOWconfig(f);
824N/A (void)close(f);
824N/A
824N/A return(OWCFG_OK);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/A****************************************************************************
824N/AExported functions...
824N/A****************************************************************************
824N/A***************************************************************************/
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigSetPackage:
824N/A
824N/AThis function establishes the name of the package to associate with
824N/Adatabase resources created by subsequent calls to OWconfigSetAttribute or
824N/AOWconfigCreateClass.
824N/A
824N/AReturn: None.
824N/A***************************************************************************/
824N/Avoid
824N/AOWconfigSetPackage(char *package)
824N/A{
824N/A if (package)
824N/A (void)strcpy(currentPackage, package);
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigRemovePackage:
824N/A
824N/AThis function removes any resources from the database that were
824N/Aassociated with the named package.
824N/A
824N/AReturn: OWCFG_OK or !OWCFG_OK.
824N/A
824N/ANote: The data structure is not really optimal for searching by package,
824N/Abut performance isn't really critical here.
824N/A***************************************************************************/
824N/Aint
824N/AOWconfigRemovePackage(char *package)
824N/A{
824N/A struct nodeStruct *cp, *ip;
824N/A int result = OWCFG_PKGNAME;
824N/A
824N/A if (!package)
824N/A return(OWCFG_ARGS);
824N/A
824N/A cp = OWconfigDatabase.head;
824N/A while (cp) {
824N/A ip = cp->head;
824N/A while(ip) {
824N/A char *pkg = ip->nodeValue.instance.pkg;
824N/A
824N/A if (pkg && !strcmp(pkg, package)) {
824N/A struct nodeStruct *next = ip->next;
824N/A
824N/A ip->nodeFree(ip);
824N/A ip = next;
824N/A result = OWCFG_OK;
824N/A continue;
824N/A }
824N/A ip = ip->next;
824N/A }
824N/A cp = cp->next;
824N/A }
824N/A
824N/A return(result);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigSetInstance:
824N/A
824N/A"OWconfigSetInstance" is a convenient front end to "OWconfigSetAttribute".
824N/AIt takes a list of attributes and adds them to an instance of a class.
824N/AIf that class and/or instance does not already exist, they are or it is created.If that instance does exist, replacements, when necessary, occur on a per
824N/Aattribute/value pair basis, otherwise they are merely added to the instance.
824N/A
824N/AReturn: OWCFG_OK or !OWCFG_OK(could occur during an out of memory condition).
824N/A***************************************************************************/
824N/Aint
824N/AOWconfigSetInstance(char *class, char *name, OWconfigAttributePtr attr,
824N/A int numberInattr)
824N/A{
824N/A OWconfigAttributePtr limit;
824N/A int result = OWCFG_OK;
824N/A
824N/A if (!(class && name && attr))
824N/A return(OWCFG_ARGS);
824N/A
824N/A limit = attr + numberInattr;
824N/A
824N/A for (;attr < limit; attr++) {
824N/A result = OWconfigSetAttribute(class, name,
824N/A attr->attribute,
824N/A attr->value);
824N/A if (result != OWCFG_OK)
824N/A break;
824N/A }
824N/A
824N/A return(result);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigRemoveInstance:
824N/A
824N/A"OWconfigRemoveInstance" removes an instance of a class, identified by
824N/A"class" and "name".
824N/A
824N/AReturn: OWCFG_OK or !OWCFG_OK
824N/A***************************************************************************/
824N/Aint
824N/AOWconfigRemoveInstance(char *class, char *name)
824N/A{
824N/A struct nodeStruct *ip;
824N/A
824N/A if (!(class && name))
824N/A return(OWCFG_ARGS);
824N/A
824N/A ip = searchInstance(class, name);
824N/A if (!ip)
824N/A return(OWCFG_INSTANCENAME);
824N/A
824N/A ip->nodeFree(ip);
824N/A
824N/A return(OWCFG_OK);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigSetAttribute:
824N/A
824N/A"OWconfigSetAttribute" takes an attribute/value pair and adds it to an
824N/Ainstance of a class. If that class and/or instance does not already
824N/Aexist, they are or it is created. If the named attribute already exists
824N/Awithin the instance, it is replaced.
824N/A
824N/AReturn: OWCFG_OK or !OWCFG_OK(could occur during with out of memory condition).
824N/A***************************************************************************/
824N/Aint
824N/AOWconfigSetAttribute(char *class, char *name, char *attribute, char *value)
824N/A{
824N/A struct nodeStruct *cp, *ip, *ap;
824N/A char *tmpPkg;
824N/A
824N/A if (!(class && name && attribute && value))
824N/A return(OWCFG_ARGS);
824N/A
824N/A cp = searchClass(class);
824N/A if (!cp) {
824N/A cp = createClass(class);
824N/A if (!cp)
824N/A return(OWCFG_ALLOC);
824N/A }
824N/A
824N/A ip = searchNodeList(cp->head, name);
824N/A if (!ip) {
824N/A ip = createInstance(class, name);
824N/A if (!ip)
824N/A return(OWCFG_ALLOC);
824N/A }
824N/A
824N/A ap = searchNodeList(ip->head, attribute);
824N/A if (ap) {
824N/A if (ap->nodeValue.attr.value)
824N/A freeMem(ap->nodeValue.attr.value);
824N/A } else {
824N/A ap = (struct nodeStruct *)
824N/A allocMem(sizeof(struct nodeStruct));
824N/A if (!ap)
824N/A return(OWCFG_ALLOC);
824N/A ap->name = dupString(attribute);
824N/A if (!ap->name) {
824N/A freeMem(ap);
824N/A return(OWCFG_ALLOC);
824N/A }
824N/A ap->hashValue = hashValue(attribute);
824N/A ap->parent = ip;
824N/A ap->head = NULL;
824N/A ap->tail = NULL;
824N/A ap->nodeFree = freeAttr;
824N/A
824N/A if (!ip->head)
824N/A ip->head = ap;
824N/A
824N/A ap->prev = ip->tail;
824N/A ap->next = NULL;
824N/A
824N/A if (ip->tail)
824N/A ip->tail->next = ap;
824N/A
824N/A ip->tail = ap;
824N/A }
824N/A
824N/A ap->nodeValue.attr.value = dupString(value);
824N/A if (!ap->nodeValue.attr.value) {
824N/A freeAttr(ap);
824N/A return(OWCFG_ALLOC);
824N/A }
824N/A
824N/A if (!ip->nodeValue.instance.pkg) {
824N/A tmpPkg = dupString(currentPackage);
824N/A if (!tmpPkg)
824N/A return(OWCFG_ALLOC);
824N/A ip->nodeValue.instance.pkg = tmpPkg;
824N/A }
824N/A
824N/A return(OWCFG_OK);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigGetClassNames:
824N/A
824N/A"OWconfigGetClassNames" returns a list of the names of all the
824N/Ainstances of the named class. The end of the list is indicated by
824N/Aa NULL pointer. All users of this function may call "OWconfigFreeClassNames"
824N/Ato free the list and the strings it points to.
824N/A
824N/AReturn: (char **) to list of class instance names or NULL if class did
824N/A not exist.
824N/A***************************************************************************/
824N/Achar **
824N/AOWconfigGetClassNames(char *class)
824N/A{
824N/A struct nodeStruct *cp, *ip;
824N/A int instanceCount = 0;
824N/A char **listOfString, **ptr;
824N/A
824N/A if (!class)
824N/A return(NULL);
824N/A
824N/A cp = searchClass(class);
824N/A if (!cp)
824N/A return(NULL);
824N/A
824N/A /*** Count the number of instances in the class... ***/
824N/A for (ip=cp->head; ip; ip=ip->next)
824N/A instanceCount++;
824N/A
824N/A listOfString = (char **)allocMem((instanceCount+1) * sizeof(char *));
824N/A if (listOfString) {
824N/A for (ptr=listOfString, ip=cp->head;
824N/A ip;
824N/A ptr++, ip=ip->next)
824N/A {
824N/A *ptr = dupString(ip->name);
824N/A
824N/A /*** If dupString fails, free previously allocated
824N/A strings and return NULL...
824N/A ***/
824N/A if (!(*ptr)) {
824N/A char **limit = ptr;
824N/A
824N/A for (ptr = listOfString;
824N/A ptr < limit;
824N/A ptr++)
824N/A {
824N/A freeMem(*ptr);
824N/A }
824N/A
824N/A freeMem(listOfString);
824N/A return(NULL);
824N/A }
824N/A }
824N/A *ptr = NULL;
824N/A }
824N/A
824N/A return(listOfString);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigFreeClassNames:
824N/A
824N/A"OWconfigFreeClassNames" frees the list of class names returned by
824N/A"OWconfigGetClassNames".
824N/A***************************************************************************/
824N/Avoid
824N/AOWconfigFreeClassNames(char **list)
824N/A{
824N/A char **ptr;
824N/A
824N/A if (!list)
824N/A return;
824N/A
824N/A for (ptr = list; *ptr; ptr++)
824N/A freeMem(*ptr);
824N/A
824N/A freeMem(list);
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigGetInstance:
824N/A
824N/A"OWconfigGetInstance" returns a list of attribute definitions belonging
824N/Ato the instance identified by "class" and "name". Use "OWconfigFreeInstance"
824N/Ato free the memory allocated to the information returned by
824N/A"OWconfigGetInstance".
824N/A
824N/AReturn:
824N/A OWconfigAttributePtr or NULL (if instance doesn't exist).
824N/A***************************************************************************/
824N/AOWconfigAttributePtr
824N/AOWconfigGetInstance(char *class, char *name, int *numberInAttr)
824N/A{
824N/A struct nodeStruct *ip, *ap;
824N/A int attrCount = 0;
824N/A OWconfigAttributePtr replyPtr, ptr;
824N/A
824N/A if ((!class) || (!name) || (!numberInAttr))
824N/A return(NULL);
824N/A
824N/A ip = searchInstance(class, name);
824N/A if (!ip)
824N/A return(NULL);
824N/A
824N/A /*** Count the number of attributes in the instance... ***/
824N/A for (ap = ip->head; ap; ap=ap->next)
824N/A attrCount++;
824N/A
824N/A replyPtr = (OWconfigAttributePtr)allocMem(attrCount * sizeof(*replyPtr));
824N/A if (replyPtr) {
824N/A for (ptr=replyPtr, ap=ip->head;
824N/A ap;
824N/A ptr++, ap=ap->next)
824N/A {
824N/A ptr->attribute = dupString(ap->name);
824N/A ptr->value = dupString(ap->nodeValue.attr.value);
824N/A if ((!ptr->attribute) || (!ptr->value)) {
824N/A OWconfigAttributePtr limit=ptr;
824N/A
824N/A if (ptr->attribute)
824N/A freeMem(ptr->attribute);
824N/A else
824N/A freeMem(ptr->value);
824N/A
824N/A for (ptr = replyPtr;
824N/A ptr < limit;
824N/A ptr++)
824N/A {
824N/A freeMem(ptr->attribute);
824N/A freeMem(ptr->value);
824N/A }
824N/A
824N/A freeMem(replyPtr);
824N/A return(NULL);
824N/A }
824N/A }
824N/A *numberInAttr = attrCount;
824N/A }
824N/A
824N/A return(replyPtr);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigFreeInstance:
824N/A
824N/A"OWconfigFreeInstance" frees the data returned by OWconfigGetInstance.
824N/A***************************************************************************/
824N/Avoid
824N/AOWconfigFreeInstance(OWconfigAttributePtr attr, int numberInAttr)
824N/A{
824N/A OWconfigAttributePtr ptr, limit;
824N/A
824N/A if ((!attr) || (!numberInAttr))
824N/A return;
824N/A
824N/A for (ptr = attr, limit = attr + numberInAttr;
824N/A ptr < limit;
824N/A ptr++)
824N/A {
824N/A freeMem(ptr->attribute);
824N/A freeMem(ptr->value);
824N/A }
824N/A
824N/A freeMem(attr);
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigGetAttribute:
824N/A
824N/A"OWconfigGetAttribute" returns the string value of the requested attribute.
824N/A
824N/AReturn: (char *) to value of attribute or NULL if attribute could not
824N/A be found.
824N/A***************************************************************************/
824N/Achar *
824N/AOWconfigGetAttribute(char *class, char *name, char *attribute)
824N/A{
824N/A struct nodeStruct *ap;
824N/A
824N/A if (!(class && name && attribute))
824N/A return(NULL);
824N/A
824N/A ap = searchAttr(class, name, attribute);
824N/A if (ap)
824N/A return(dupString(ap->nodeValue.attr.value));
824N/A else
824N/A return(NULL);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigFreeAttribute:
824N/A
824N/A"OWconfigFreeAttribute" frees the string returned by OWconfigGetAttribute.
824N/A***************************************************************************/
824N/Avoid
824N/AOWconfigFreeAttribute(char *attribute)
824N/A{
824N/A if (attribute)
824N/A freeMem(attribute);
824N/A
824N/A return;
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigClose:
824N/A
824N/AIf writefile was specified, the existing target file, if any, is write locked
824N/Ausing fcntl. If the lock succeeds, the new OWconfig file is written to the
824N/Asame directory, with a temporary name. The old file is removed and the new
824N/Afile is renamed to match the old file.
824N/A
824N/AThe internal database is freed.
824N/A
824N/AReturn: OWCFG_OK or !OWCFG_OK(could occur if write or write lock failed).
824N/A
824N/ANote: When a file is written, all comments are lost from the
824N/Aoriginal file(s). When written, the OWconfig entries will be grouped by class.
824N/A***************************************************************************/
824N/Aint
824N/AOWconfigClose(char *writeFile)
824N/A{
824N/A int result = OWCFG_OK;
824N/A
824N/A if (writeFile != NULL)
824N/A result = writeOWconfig(writeFile);
824N/A
824N/A initDatabase();
824N/A return(result);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigValidate: Verifies that the internal database is up to date
824N/A with respect to the database file indicated by the global "readFlags".
824N/A If it isn't, the files are re-read and a new internal database is
824N/A created.
824N/A
824N/AReturn:
824N/A OWCFG_OK or !OWCFG_OK (if re-read fails).
824N/A***************************************************************************/
824N/Aint
824N/AOWconfigValidate(void)
824N/A{
824N/A int f;
824N/A int result=OWCFG_OK;
824N/A int validate = 0;
824N/A struct stat statbuf;
824N/A
824N/A if (readFile1) {
824N/A f = open(readFile1, O_RDONLY);
824N/A if (f == -1)
824N/A return(OWCFG_OPEN1FAIL); /*Leave well enough alone*/
824N/A if (fstat(f, &statbuf) == -1) {
824N/A (void)close(f);
824N/A return(OWCFG_FSTAT1FAIL); /*Leave well enough alone*/
824N/A }
824N/A if (statbuf.st_mtime > readFile1TimeStamp)
824N/A validate = 1;
824N/A
824N/A (void)close(f);
824N/A }
824N/A
824N/A if (!validate && readFile2) {
824N/A f = open(readFile2, O_RDONLY);
824N/A if (f == -1)
824N/A return(OWCFG_OPEN2FAIL); /*Leave well enough alone*/
824N/A if (fstat(f, &statbuf) == -1) {
824N/A (void)close(f);
824N/A return(OWCFG_FSTAT2FAIL); /*Leave well enough alone*/
824N/A }
824N/A if (statbuf.st_mtime > readFile2TimeStamp)
824N/A validate = 1;
824N/A
824N/A (void)close(f);
824N/A }
824N/A
824N/A if (validate) {
824N/A struct nodeStruct *oldHead, *oldTail;
824N/A
824N/A oldHead = OWconfigDatabase.head;
824N/A oldTail = OWconfigDatabase.tail;
824N/A /*** Setting databaseValid to zero causes initDatabase()
824N/A to NOT free existing database...
824N/A ***/
824N/A databaseValid = 0;
824N/A result = OWconfigInit(readFile1, readFile2, OWconfigFlags,
824N/A allocMem, freeMem);
824N/A if (result != OWCFG_OK) {
824N/A OWconfigDatabase.head = oldHead;
824N/A OWconfigDatabase.tail = oldTail;
824N/A databaseValid = 1;
824N/A } else {
824N/A freeNodeList(oldHead);
824N/A }
824N/A }
824N/A
824N/A return(result);
824N/A}
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A
824N/A/***************************************************************************
824N/AOWconfigInit:
824N/A
824N/A"OWconfigInit" will read the OWconfig files named by readfile1 and
824N/Areadfile2.
824N/AClass instances and attribute/value pairs read from readfile2 will override
824N/Athose read from readfile1. The replacement will occur on a per
824N/Aattribute/value pair basis. Before a database file is read, it is
824N/Aread locked using the fcntl facility. Immediately after the file
824N/Ais read, it is unlocked.
824N/A
824N/AReturn: OWCFG_OK or !OWCFG_OK. Bogus filepaths can return !OWCFG_OK.
824N/A If readfile1 and readfile2 are both non-NULL, and the read of
824N/A readfile1 succeeds but the read of readfile2 fails, OWCFG_OK
824N/A will be returned. Lock test failures will return !OWCFG_OK.
824N/A***************************************************************************/
824N/A
824N/Aint
824N/AOWconfigInit(char *readfile1, char *readfile2, int flags,
824N/A void *(*allocmem)(unsigned), void (*freemem)(void *))
824N/A{
824N/A int result, result1, result2;
824N/A
824N/A if (allocmem)
824N/A allocMem = allocmem;
824N/A else
824N/A allocMem = malloc;
824N/A
824N/A if (freemem)
824N/A freeMem = freemem;
824N/A else
824N/A freeMem = free;
824N/A
824N/A initDatabase();
824N/A
824N/A if (readfile1 != readFile1)
824N/A readFile1 = dupString(readfile1);
824N/A
824N/A if (readfile2 != readFile2)
824N/A readFile2 = dupString(readfile2);
824N/A
824N/A OWconfigFlags = flags;
824N/A lineNumber = 0;
824N/A lastLineNumber = 0;
824N/A
824N/A /*** Check for specific corner cases... ***/
824N/A if (readFile1 == NULL && readFile2 == NULL)
824N/A return(OWCFG_OK);
824N/A
824N/A
824N/A /*** Read file 1, if specified... ***/
824N/A result1 = OWCFG_OK;
824N/A if (readFile1) {
824N/A result1 = readOWconfig(readFile1, &readFile1TimeStamp);
824N/A if (result1 != OWCFG_OK && result1 != OWCFG_OPEN1FAIL) {
824N/A initDatabase();
824N/A return(result1);
824N/A }
824N/A }
824N/A
824N/A
824N/A /*** Read file 2, if specified... ***/
824N/A lastLineNumber = lineNumber;
824N/A result2 = OWCFG_OK;
824N/A if (readFile2) {
824N/A result2 = readOWconfig(readFile2, &readFile2TimeStamp);
824N/A if (result2 != OWCFG_OK && result2 != OWCFG_OPEN1FAIL) {
824N/A initDatabase();
824N/A if (result2 == OWCFG_LOCK1FAIL)
824N/A result2 = OWCFG_LOCK2FAIL;
824N/A if (result2 == OWCFG_SYNTAX1)
824N/A result2 = OWCFG_SYNTAX2;
824N/A return(result2);
824N/A }
824N/A }
824N/A
824N/A (void)strcpy(currentPackage, defaultNewPkgName);
824N/A
824N/A if (result1 == result2) {
824N/A if (result1 == OWCFG_OK)
824N/A return(OWCFG_OK);
824N/A else
824N/A return(OWCFG_OPENBOTHFAIL);
824N/A } else {
824N/A if (result1 == OWCFG_OPEN1FAIL)
824N/A return(OWCFG_OPEN1FAIL);
824N/A else
824N/A return(OWCFG_OPEN2FAIL);
824N/A }
824N/A
824N/A}
824N/A
824N/A