mirror of
https://github.com/mabam/CAP.git
synced 2024-06-14 05:29:33 +00:00
403 lines
9.3 KiB
C
403 lines
9.3 KiB
C
|
static char rcsid[] = "$Author: djh $ $Date: 1995/08/28 10:38:35 $";
|
||
|
static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/parse.c,v 2.1 1995/08/28 10:38:35 djh Rel djh $";
|
||
|
static char revision[] = "$Revision: 2.1 $";
|
||
|
|
||
|
/*
|
||
|
* parse.c - read a configuration file and parse the information
|
||
|
*
|
||
|
* UNIX AppleTalk spooling program: act as a laserwriter
|
||
|
* AppleTalk package for UNIX (4.2 BSD).
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <sys/param.h>
|
||
|
#include <sys/file.h>
|
||
|
#include <netat/sysvcompat.h>
|
||
|
#include <netat/compat.h>
|
||
|
#ifdef USESTRINGDOTH
|
||
|
#include <string.h>
|
||
|
#else /* USESTRINGDOTH */
|
||
|
#include <strings.h>
|
||
|
#endif /* USESTRINGDOTH */
|
||
|
#ifdef NEEDFCNTLDOTH
|
||
|
#include <sys/fcntl.h>
|
||
|
#endif /* NEEDFCNTLDOTH */
|
||
|
#ifndef NONDBM
|
||
|
# include <ndbm.h>
|
||
|
#else /* NONDBM */
|
||
|
# include <dbm.h>
|
||
|
#endif /* NONDBM */
|
||
|
#include "list.h"
|
||
|
#include "parse.h"
|
||
|
|
||
|
typedef unsigned short unshort;
|
||
|
|
||
|
char datasuffix[] = ".dat";
|
||
|
char includename[] = "-";
|
||
|
char keywords_key[] = "keywords\0001.0.0";
|
||
|
KVTree **_printers;
|
||
|
char specialOpts[] = "LT";
|
||
|
KVTree **thequery;
|
||
|
|
||
|
extern char *myname;
|
||
|
extern List *optionlist;
|
||
|
extern List *printerlist;
|
||
|
|
||
|
static char *keywords = NULL;
|
||
|
static KVTree **pass1;
|
||
|
#ifndef NONDBM
|
||
|
static DBM *printerdb;
|
||
|
#endif NONDBM
|
||
|
static int printerfd;
|
||
|
|
||
|
char *malloc();
|
||
|
|
||
|
static void Construct();
|
||
|
static char *FetchData();
|
||
|
static void Include();
|
||
|
static void _Include();
|
||
|
static List *UnpackList();
|
||
|
static List *Unpackdb();
|
||
|
static void _configargs();
|
||
|
static void setargs();
|
||
|
|
||
|
static void
|
||
|
Construct(name, kp, lp)
|
||
|
char *name;
|
||
|
register KVTree **kp;
|
||
|
List *lp;
|
||
|
{
|
||
|
register void **vp;
|
||
|
register int i;
|
||
|
register void *np;
|
||
|
|
||
|
for (vp = (void **)AddrList(lp), i = NList(lp); i > 0; i -= 2) {
|
||
|
if (strcmp((char *)*vp, includename) == 0) { /* include */
|
||
|
Include(name, (char *)*++vp, kp);
|
||
|
vp++;
|
||
|
continue;
|
||
|
}
|
||
|
np = *vp++;
|
||
|
if (isOption(np) && isSpecialOpt(np)) {
|
||
|
if ((lp = (List *)SearchKVTree(kp, np, strcmp)) == NULL) {
|
||
|
lp = CreateList();
|
||
|
AddToKVTree(kp, np, lp, strcmp);
|
||
|
}
|
||
|
AddToList(lp, *vp++);
|
||
|
} else
|
||
|
AddToKVTree(kp, np, *vp++, strcmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char *
|
||
|
FetchData(name, n)
|
||
|
char *name;
|
||
|
register int n;
|
||
|
{
|
||
|
register char *ptr, *cp;
|
||
|
register int size;
|
||
|
datum key, data;
|
||
|
Location loc;
|
||
|
|
||
|
key.dptr = name;
|
||
|
key.dsize = n;
|
||
|
#ifndef NONDBM
|
||
|
data = dbm_fetch(printerdb, key);
|
||
|
#else NONDBM
|
||
|
data = fetch(key);
|
||
|
#endif NONDBM
|
||
|
if (!data.dptr)
|
||
|
return(NULL);
|
||
|
if (data.dsize != sizeof(Location)) {
|
||
|
fprintf(stderr, "%s: location data for %s is wrong size\n",
|
||
|
myname, name);
|
||
|
exit(1);
|
||
|
}
|
||
|
bcopy((char *)data.dptr, (char *)&loc, sizeof(Location));
|
||
|
if (loc.magic != MagicNumber || (size = loc.size) <= 0) {
|
||
|
fprintf(stderr, "%s: location data mismatch for %s\n", myname, name);
|
||
|
exit(1);
|
||
|
}
|
||
|
if (lseek(printerfd, loc.offset, L_SET) < 0) {
|
||
|
fprintf(stderr, "%s: unable to position in data file for %s\n",
|
||
|
myname, name);
|
||
|
exit(1);
|
||
|
}
|
||
|
if ((cp = ptr = malloc(size)) == NULL) {
|
||
|
fprintf(stderr, "%s: out of memory for %s\n", myname, name);
|
||
|
exit(1);
|
||
|
}
|
||
|
while (size > 0) {
|
||
|
if ((n = read(printerfd, cp, size)) < 0) {
|
||
|
fprintf(stderr, "%s: read error on %s\n", myname, name);
|
||
|
exit(1);
|
||
|
}
|
||
|
if (n == 0) {
|
||
|
fprintf(stderr, " %s: premature end of file on %s\n", myname, name);
|
||
|
exit(1);
|
||
|
}
|
||
|
size -= n;
|
||
|
cp += n;
|
||
|
}
|
||
|
return(ptr);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
Include(name, cp, kp)
|
||
|
char *name, *cp;
|
||
|
KVTree **kp;
|
||
|
{
|
||
|
register KVTree **ip;
|
||
|
register List *lp;
|
||
|
register char *dp;
|
||
|
|
||
|
if (ip = (KVTree **)SearchKVTree(_printers, (void *)cp, strcmp)) {
|
||
|
_Include(kp, *ip);
|
||
|
return;
|
||
|
}
|
||
|
/* not in printer list, so try pass1 */
|
||
|
if (lp = (List *)SearchKVTree(pass1, (void *)cp, strcmp)) {
|
||
|
ip = CreateKVTree();
|
||
|
/*
|
||
|
* We add the new (empty) tree into master printer tree before
|
||
|
* constructing it so as to prevent infinite include loops.
|
||
|
*/
|
||
|
AddToKVTree(_printers, (void *)cp, ip, strcmp);
|
||
|
Construct(cp, ip, lp);
|
||
|
if (*ip)
|
||
|
_Include(kp, *ip);
|
||
|
NList(lp) = 0; /* mark the list as already processed */
|
||
|
return;
|
||
|
}
|
||
|
/* not in pass1, so try database */
|
||
|
if (keywords && (dp = FetchData(cp, strlen(cp)))) {
|
||
|
lp = Unpackdb(dp);
|
||
|
ip = CreateKVTree();
|
||
|
/*
|
||
|
* We add the new (empty) tree into master printer tree before
|
||
|
* constructing it so as to prevent infinite include loops.
|
||
|
*/
|
||
|
AddToKVTree(_printers, cp, ip, strcmp);
|
||
|
Construct(cp, ip, lp);
|
||
|
if (*ip)
|
||
|
_Include(kp, *ip);
|
||
|
return;
|
||
|
}
|
||
|
fprintf(stderr, "%s: %s: Can't include %s\n", myname, name, cp);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
_Include(kp, ip)
|
||
|
KVTree **kp;
|
||
|
register KVTree *ip;
|
||
|
{
|
||
|
register List *lp;
|
||
|
|
||
|
if (ip == NULL)
|
||
|
return;
|
||
|
if (isOption(ip->key) && isSpecialOpt(ip->key) &&
|
||
|
(lp = (List *)SearchKVTree(kp, ip->key, strcmp))) {
|
||
|
CatList(lp, (List *)ip->val);
|
||
|
} else
|
||
|
AddToKVTree(kp, ip->key, ip->val, strcmp);
|
||
|
if (ip->left)
|
||
|
_Include(kp, ip->left);
|
||
|
if (ip->right)
|
||
|
_Include(kp, ip->right);
|
||
|
}
|
||
|
|
||
|
static List *
|
||
|
UnpackList(sp, c)
|
||
|
register unshort *sp;
|
||
|
register char *c;
|
||
|
{
|
||
|
register List *lp;
|
||
|
register int n;
|
||
|
|
||
|
lp = CreateList();
|
||
|
for (n = *sp++; n > 0; n--)
|
||
|
AddToList(lp, c + *sp++);
|
||
|
return(lp);
|
||
|
}
|
||
|
|
||
|
static List *
|
||
|
Unpackdb(c)
|
||
|
register char *c;
|
||
|
{
|
||
|
register unshort *sp, *s;
|
||
|
register char *cp;
|
||
|
register List *lp;
|
||
|
register int n;
|
||
|
|
||
|
lp = CreateList();
|
||
|
s = (unshort *)c;
|
||
|
/*
|
||
|
* The first unshort is offset to string section. s is now pointing to
|
||
|
* beginning of packed ushorts
|
||
|
*/
|
||
|
c += *s++;
|
||
|
/*
|
||
|
* The first unshort is the number of pairs in the list. Then each following
|
||
|
* pair of ushorts points to a name string and the value, which may be another
|
||
|
* string or another list.
|
||
|
*/
|
||
|
sp = s;
|
||
|
for (n = *sp++; n > 0; n--) {
|
||
|
AddToList(lp, cp = keywords + *sp++);
|
||
|
if (StringVal(cp)) /* value is just a string */
|
||
|
AddToList(lp, *sp == 0 ? NULL : c + *sp);
|
||
|
else /* value is another list */
|
||
|
AddToList(lp, UnpackList(s + *sp, c));
|
||
|
sp++;
|
||
|
}
|
||
|
return(lp);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
configargs(dbname)
|
||
|
char *dbname;
|
||
|
{
|
||
|
register KVTree **kp;
|
||
|
register List *lp;
|
||
|
register void **vp;
|
||
|
register int i;
|
||
|
register char *cp;
|
||
|
KVTree **_default;
|
||
|
char buf[BUFSIZ];
|
||
|
|
||
|
if (dbname) {
|
||
|
#ifndef NONDBM
|
||
|
if ((printerdb = dbm_open(dbname, O_RDONLY, 0)) == NULL) {
|
||
|
fprintf(stderr, "%s: Can't open dbm %s\n", myname, dbname);
|
||
|
exit(1);
|
||
|
}
|
||
|
#else NONDBM
|
||
|
if (dbminit(dbname) < 0) {
|
||
|
fprintf(stderr, "%s: Can't open dbm %s\n", myname, dbname);
|
||
|
exit(1);
|
||
|
}
|
||
|
#endif NONDBM
|
||
|
strcpy(buf, dbname);
|
||
|
strcat(buf, datasuffix);
|
||
|
if ((printerfd = open(buf, O_RDONLY, 0)) < 0) {
|
||
|
fprintf(stderr, "%s: Can't open data file %s%s\n", myname, dbname,
|
||
|
datasuffix);
|
||
|
exit(1);
|
||
|
}
|
||
|
if ((keywords = FetchData(keywords_key, KEYWORDSKEYSIZE)) == NULL) {
|
||
|
fprintf(stderr, "%s: %s does not contain printer templates\n",
|
||
|
myname, dbname);
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
if (optionlist) {
|
||
|
_default = CreateKVTree();
|
||
|
Construct("Default", _default, optionlist);
|
||
|
if (NList(optionlist) > 0)
|
||
|
setargs(NULL, _default);
|
||
|
FreeKVTree(_default, NULL, NULL);
|
||
|
}
|
||
|
_printers = CreateKVTree();
|
||
|
/* Pass 1 */
|
||
|
pass1 = CreateKVTree();
|
||
|
for (vp = AddrList(printerlist), i = NList(printerlist); i > 0; i -= 2){
|
||
|
cp = (char *)*vp++;
|
||
|
AddToKVTree(pass1, (void *)cp, *vp++, strcmp);
|
||
|
}
|
||
|
/* Pass 2 */
|
||
|
for (vp = AddrList(printerlist), i = NList(printerlist); i > 0; vp++, i -= 2) {
|
||
|
if (NList(*vp) <= 0) /* already processed */
|
||
|
continue;
|
||
|
kp = CreateKVTree();
|
||
|
cp = (char *)*vp++;
|
||
|
/*
|
||
|
* We add the new (empty) tree into master printer tree before
|
||
|
* constructing it so as to prevent infinite include loops.
|
||
|
*/
|
||
|
AddToKVTree(_printers, (void *)cp, kp, strcmp);
|
||
|
Construct(cp, kp, (List *)*vp);
|
||
|
}
|
||
|
if (*_printers)
|
||
|
_configargs(*_printers);
|
||
|
|
||
|
#ifndef NONDBM
|
||
|
if (printerdb)
|
||
|
dbm_close(printerdb);
|
||
|
#else NONDBM
|
||
|
/*
|
||
|
* There does not seem to be a way to close the old dbm file!
|
||
|
*/
|
||
|
#endif NONDBM
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
_configargs(kp)
|
||
|
register KVTree *kp;
|
||
|
{
|
||
|
if (kp == NULL)
|
||
|
return;
|
||
|
if (kp->left)
|
||
|
_configargs(kp->left);
|
||
|
if (SearchKVTree(kp->val, "-p", strcmp))
|
||
|
setargs(kp->key, kp->val);
|
||
|
if (kp->right)
|
||
|
_configargs(kp->right);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
setargs(name, kp)
|
||
|
char *name;
|
||
|
register KVTree **kp;
|
||
|
{
|
||
|
register int i, j;
|
||
|
register List *lp, *lk;
|
||
|
register void **vp;
|
||
|
extern int optind;
|
||
|
|
||
|
lp = CreateList();
|
||
|
AddToList(lp, myname); /* simulating argc, argv, so this is argv[0] */
|
||
|
if (name) {
|
||
|
/*
|
||
|
* Just do "-n name" to force thequery to be set to the correct value.
|
||
|
*/
|
||
|
AddToList(lp, "-n");
|
||
|
AddToList(lp, name);
|
||
|
AddToList(lp, NULL); /* Just in case */
|
||
|
optind = 1;
|
||
|
doargs(NList(lp) - 1, AddrList(lp));
|
||
|
FreeList(lp, NULL);
|
||
|
lp = CreateList();
|
||
|
AddToList(lp, myname);
|
||
|
}
|
||
|
lk = ListKVTree(kp);
|
||
|
for (kp = (KVTree **)AddrList(lk), i = NList(lk); i > 0; kp++, i--) {
|
||
|
if (!isOption((*kp)->key))
|
||
|
break;
|
||
|
if (isSpecialOpt((*kp)->key)) {
|
||
|
for (j = NList((*kp)->val), vp = AddrList((*kp)->val); j > 0; j--) {
|
||
|
AddToList(lp, (*kp)->key);
|
||
|
AddToList(lp, *vp++);
|
||
|
}
|
||
|
} else {
|
||
|
AddToList(lp, (*kp)->key);
|
||
|
if ((*kp)->val)
|
||
|
AddToList(lp, (*kp)->val);
|
||
|
}
|
||
|
}
|
||
|
if (i > 0) {
|
||
|
while (i-- > 0) {
|
||
|
AddToKVTree(thequery, (*kp)->key, (*kp)->val, strcmp);
|
||
|
kp++;
|
||
|
}
|
||
|
}
|
||
|
FreeList(lk, NULL);
|
||
|
if (NList(lp) > 1) {
|
||
|
AddToList(lp, NULL); /* Just in case */
|
||
|
optind = 1;
|
||
|
doargs(NList(lp) - 1, AddrList(lp));
|
||
|
}
|
||
|
FreeList(lp, NULL);
|
||
|
}
|