static char rcsid[] = "$Author: djh $ $Date: 1996/09/10 14:33:00 $"; static char rcsident[] = "$Header: /mac/src/cap60/applications/lwsrv/RCS/lwsrvconfig.c,v 2.3 1996/09/10 14:33:00 djh Rel djh $"; static char revision[] = "$Revision: 2.3 $"; /* * lwsrvconfig - auxiliary program for testing configuration files * and creating printer description databases * * AppleTalk package for UNIX (4.2 BSD). * */ #include #include #include #include #include #include #include #ifdef USESTRINGDOTH # include #else /* USESTRINGDOTH */ # include #endif /* USESTRINGDOTH */ #ifdef NEEDFCNTLDOTH # include #endif NEEDFCNTLDOTH #ifndef NONDBM # include #else NONDBM # include #endif NONDBM #include "list.h" #include "packed.h" #include "parse.h" char *myname; #define F_GLOBAL (1 << F_GLOBAL_BIT) #define F_GLOBAL_BIT 0 #define F_HASARG (1 << F_HASARG_BIT) #define F_HASARG_BIT 1 #define hasarg(f) ((f) & F_HASARG) #define isglobal(f) ((f) & F_GLOBAL) #define sf(a,g) (((a) << F_HASARG_BIT) | ((g) << F_GLOBAL_BIT)) struct descrip { char *name; short flags; }; static KVTree **argname; static struct argnamebuf { char *arg; struct descrip d; } argnamebuf[] = { {"-A", {"DSC", sf(1, 0)}}, {"-C", {"LPRCommand", sf(1, 1)}}, #ifdef LPRARGS {"-L", {"LPRArgument", sf(1, 0)}}, #endif LPRARGS {"-N", {"DontCollect", sf(0, 0)}}, #ifdef PASS_THRU {"-P", {"PassThru", sf(0, 0)}}, #endif PASS_THRU #ifdef NeXT {"-R", {"NeXTResolution", sf(1, 0)}}, #endif NeXT {"-S", {"SingleFork", sf(0, 1)}}, {"-T", {"TranScriptOption", sf(1, 0)}}, #ifdef LWSRV_AUFS_SECURITY {"-X", {"AUFSSecurity", sf(1, 1)}}, #endif LWSRV_AUFS_SECURITY #ifdef LW_TYPE {"-Y", {"AppleTalkType", sf(1, 0)}}, #endif LW_TYPE {"-a", {"ProcsetDir", sf(1, 0)}}, {"-d", {"Debug", sf(1, 1)}}, {"-e", {"Alloweexec", sf(0, 0)}}, {"-f", {"FontFile", sf(1, 0)}}, {"-h", {"SuppressBanner", sf(0, 0)}}, {"-k", {"NoChecksum", sf(0, 0)}}, {"-l", {"LogFile", sf(1, 1)}}, {"-p", {"PrinterQueue", sf(1, 0)}}, {"-q", {"QueryFile", sf(1, 1)}}, {"-r", {"KeepSpoolFile", sf(0, 0)}}, {"-t", {"TraceFile", sf(1, 0)}}, {"-v", {"Verbose", sf(0, 1)}}, {NULL, NULL}, }; static char *createdb = NULL; static int datafd; long dataoffset = 0; #ifndef NONDBM static DBM *db; #endif NONDBM static char *dbname = NULL; static KVTree **_default; static int firstargs = 1; static int firstprinter = 1; static char firsttime[127]; static char *headerstr = NULL; static char null[] = ""; static int oldformat = 0; static char *printername; static int verbose = 0; int doargs(); static void addback(/* int argc, char **argv */); static void display(/* char *str, KVTree **kp */); static void displaytemplates(); static void docreatedb(); static KVTree **initargname(); static int getflags(/* char *str */); static char *keyname(/* char *str */); static char *quotestr(/* char *str */); static void setfirsttime(/* char *str */); static void storedata(/* char *name, int n, char *ptr, int size */); static unshort *ushortdup(/* int i */); static char *untab(/* char *str */); static void usage(); main(argc, argv) int argc; char **argv; { register int c; register KVTree **kp; register List *lp; register FILE *fp; extern FILE *yyin; extern char *optarg; extern int optind; if (myname = rindex(*argv, '/')) myname++; else myname = *argv; while ((c = getopt(argc, argv, "c:l:ov?")) != EOF) { switch(c) { case 'c': createdb = optarg; break; case 'l': dbname = optarg; break; case 'o': oldformat++; break; case 'v': verbose++; break; case '?': default: usage(); } } if (createdb && dbname) usage(); if (optind < argc) { if ((argc - optind) > 1) usage(); if ((fp = fopen(argv[optind], "r")) == NULL) { fprintf(stderr, "%s: Can't open %s\n", myname, argv[optind]); exit(1); } } else fp = stdin; yyin = fp; /* set for flex(1) */ argname = initargname(); initkeyword(fp); umask(0133); if (yyparse()) exit(1); if (!dbname && libraryfile) dbname = libraryfile; if (createdb) docreatedb(); else { _default = thequery = CreateKVTree(); setfirsttime(specialOpts); configargs(dbname); } exit(0); } static void addback(argc, argv) register int argc; register char **argv; { register void *n; register List *lp; register int f; while (argc-- > 0) { f = getflags(*argv); if (hasarg(f)) { n = (void *)*argv++; if (isSpecialOpt(n)) { if (firsttime[Option(n)]) { firsttime[Option(n)] = 0; if (lp = (List *)SearchKVTree(thequery, n, strcmp)) { if (thequery == _default) { AddToList(lp, (void *)*argv); } else { lp = DupList(lp); AddToList(lp, (void *)*argv); AddToKVTree(thequery, n, (void *)lp, strcmp); } } else { lp = CreateList(); AddToList(lp, (void *)*argv); AddToKVTree(thequery, n, (void *)lp, strcmp); } } else { lp = (List *)SearchKVTree(thequery, n, strcmp); AddToList(lp, (void *)*argv); } } else AddToKVTree(thequery, n, (void *)*argv, strcmp); argv++; argc--; } else AddToKVTree(thequery, (void *)*argv++, NULL, strcmp); } } /* * doargs would normally set the arguments in lwsrv. We intercept this * to do our printing. */ doargs(argc, argv) int argc; char **argv; { register int n, i, f; register char **a; argc--; argv++; if (firstargs && strcmp(*argv, "-n") != 0) { /* options */ firstargs = 0; if (verbose) { addback(argc, argv); display("Options", thequery); } else { n = argc; a = argv; i = 0; while (n-- > 0) { f = getflags(*a); if (isglobal(f)) i++; if (hasarg(f)) { a++; n--; } a++; } if (i > 0) { printf("Options = %s", i > 1 ? "(\n" : null); n = argc; a = argv; while (n-- > 0) { f = getflags(*a); if (isglobal(f)) { printf("%s%s", i > 1 ? "\t" : null, keyname(*a)); if (hasarg(f)) { printf(" %s;\n", quotestr(*++a)); n--; } else fputs(";\n", stdout); if (i == 1) break; } else { if (hasarg(f)) { a++; n--; } } a++; } if (i > 1) fputs(");\n\n", stdout); else putchar('\n'); } addback(argc, argv); } } else if (strcmp(*argv, "-n") == 0) { /* setup thequery so setargs will insert the queries in the right one */ firstargs = 0; if (thequery != _default) FreeKVTree(thequery, NULL, NULL); thequery = DupKVTree(_default); if (verbose && firstprinter) { /* print the templates */ firstprinter = 0; displaytemplates(); } setfirsttime(specialOpts); printername = *++argv; } else { /* actually do the printer */ addback(argc, argv); display(printername, thequery); } } static void docreatedb() { register KVTree **keys; register PackedChar *ckeys; register PackedChar *pc; register PackedShort *ps; register void **v2, **v3, **vp; register int i, j, k; register unshort *sp, *sp2; register char *name; char buf[BUFSIZ]; if (verbose) printf("Creating database %s\n", createdb); strcpy(buf, createdb); strcat(buf, ".dir"); unlink(buf); strcpy(buf, createdb); strcat(buf, ".pag"); unlink(buf); #ifndef NONDBM if ((db = dbm_open(createdb, O_RDWR | O_CREAT, 0755)) == NULL) { fprintf(stderr, "%s: Can't create database %s\n", myname, createdb); exit(1); } #else NONDBM if ((i = creat(buf, 0755)) < 0) { fprintf(stderr, "%s: Can't create %s\n", myname, buf); exit(1); } if ((i = creat(buf, 0755)) < 0) { fprintf(stderr, "%s: Can't create %s\n", myname, buf); exit(1); } if (dbminit(creatdb) < 0) { fprintf(stderr, "%s: Can't open database %s\n", myname, createdb); exit(1); } #endif NONDBM strcpy(buf, createdb); strcat(buf, datasuffix); unlink(buf); if ((datafd = open(buf, O_WRONLY | O_CREAT, 0755)) < 0) { fprintf(stderr, "%s: Can't create %s\n", myname, buf); exit(1); } keys = CreateKVTree(); ckeys = CreatePackedChar(); for (i = NList(printerlist), vp = AddrList(printerlist); i > 0; i -= 2) { name = (char *)*vp++; if (verbose) printf("\tCreating template %s\n", name); pc = CreatePackedChar(); /* * Since a zero means the a string value is null, we "use up" * the zero so that it can never occur in our data (except to mean * that the string is NULL */ AddToPackedChar(pc, null); ps = CreatePackedShort(); AddToPackedShort(ps, (j = NList(*vp) / 2)); sp = AllocatePackedShort(ps, 2 * j); for (v2 = AddrList(*vp); j > 0; j--) { if (verbose) printf("\t\tAdding keyword %s\n", untab((char *)*v2)); if ((sp2 = (unshort *)SearchKVTree(keys, *v2, strcmp)) == NULL) { k = AddToPackedChar(ckeys, (char *)*v2); sp2 = ushortdup(k); AddToKVTree(keys, *v2, (void *)sp2, strcmp); } *sp++ = *sp2; if (StringVal(*v2)) { v2++; *sp++ = *v2 ? AddToPackedChar(pc, (char *)*v2) : 0; } else { v2++; k = NList(*v2); *sp++ = AddToPackedShort(ps, k); for (v3 = AddrList(*v2); k > 0; k--) AddToPackedShort(ps, AddToPackedChar(pc, (char *)*v3++)); } v2++; } j = (NPackedShort(ps) + 1) * sizeof(unshort); k = NPackedChar(pc) * sizeof(char); if ((sp = (unshort *)malloc(j + k)) == NULL) errorexit(1, "docreatedb: Out of memory\n"); *sp = j; bcopy((char *)AddrPackedShort(ps), (char *)(sp + 1), NPackedShort(ps) * sizeof(unshort)); bcopy((char *)AddrPackedChar(pc), (char *)sp + j, k); storedata(name, strlen(name), (char *)sp, j + k); vp++; } if (verbose) printf("Adding keywords to database %s\n", createdb); storedata(keywords_key, KEYWORDSKEYSIZE, AddrPackedChar(ckeys), NPackedChar(ckeys) * sizeof(char), db); #ifndef NONDBM dbm_close(db); if (verbose) printf("Closing database %s\n", createdb); #else NONDBM /* * There does not seem to be a way to close the old dbm file! */ #endif NONDBM } static void storedata(name, n, ptr, size) char *name; register int n; register char *ptr; register int size; { register char *cp; datum key, data; Location loc; key.dptr = name; key.dsize = n; loc.magic = MagicNumber; /* to identify a real lwsrvconfig database */ loc.offset = dataoffset; loc.size = size; data.dptr = (char *)&loc; data.dsize = sizeof(Location); #ifndef NONDBM if (dbm_store(db, key, data, DBM_REPLACE) < 0) { fprintf(stderr, "%s: Failed to insert %s into database %s \n", myname, name, createdb); exit(1); } #else NONDBM if (store(key, data) < 0) { fprintf(stderr, "%s: Failed to insert %s into database %s \n", myname, name, createdb); exit(1); } #endif NONDBM dataoffset += size; while (size > 0) { if ((n = write(datafd, ptr, size)) <= 0) { fprintf(stderr, "%s: write error on %d%s\n", myname, createdb, datasuffix); exit(1); } size -= n; ptr += n; } } static void display(name, kp) char *name; register KVTree **kp; { register List *lp; register char **cp; register int n, i; lp = ListKVTree(kp); if (headerstr) { fputs(headerstr, stdout); headerstr = NULL; } printf("%s = ", quotestr(name)); kp = (KVTree **)AddrList(lp); if ((n = NList(lp)) == 1) { fputs(untab((char *)(*kp)->key), stdout); if (ListVal((*kp)->key)) { cp = (char **)AddrList((*kp)->val); if ((i = NList((*kp)->val)) == 1) printf(" %s;\n", quotestr(*cp)); else if (isSpecialOpt((*kp)->key)) { printf(" %s;\n", quotestr(*cp)); while (--i > 0) { fputs(untab((char *)(*kp)->key), stdout); printf(" %s;\n", quotestr(*++cp)); } } else { fputs(" (\n", stdout); while (i--) { printf("\t%s,\n", quotestr(*cp)); cp++; } fputs(");\n", stdout); } } else { if ((*kp)->val) printf(" %s;\n", quotestr((char *)(*kp)->val)); else fputs(";\n", stdout); } } else { fputs("(\n", stdout); for (;n-- > 0; kp++) { printf("\t%s", untab((char *)(*kp)->key)); if (ListVal((*kp)->key)) { cp = (char **)AddrList((*kp)->val); if ((i = NList((*kp)->val)) == 1) printf(" %s;\n", quotestr(*cp)); else if (isSpecialOpt((*kp)->key)) { printf(" %s;\n", quotestr(*cp)); while (--i > 0) { printf("\t%s", untab((char *)(*kp)->key)); printf(" %s;\n", quotestr(*++cp)); } } else { fputs(" (\n", stdout); while (i--) { printf("\t\t%s,\n", quotestr(*cp)); cp++; } fputs("\t);\n", stdout); } } else { if ((*kp)->val) printf(" %s;\n", quotestr((char *)(*kp)->val)); else fputs(";\n", stdout); } } fputs(");\n", stdout); } } static void displaytemplates() { register List *lp; register KVTree **kp; register int n; lp = ListKVTree(_printers); headerstr = "\nTemplates:\n"; for (kp = (KVTree **)AddrList(lp), n = NList(lp); n > 0; kp++, n--) { if (SearchKVTree((*kp)->val, "-p", strcmp) == NULL) display((*kp)->key, (*kp)->val, 0); } headerstr = "\nPrinters:\n"; FreeList(lp, NULL); } static KVTree ** initargname() { register KVTree **kp; register struct argnamebuf *ap; kp = CreateKVTree(); for (ap = argnamebuf; ap->arg; ap++) AddToKVTree(kp, (void *)ap->arg, (void *)&ap->d, strcmp); return(kp); } static int getflags(str) char *str; { register struct descrip *sp; if ((sp = (struct descrip *)SearchKVTree(argname, str, strcmp)) == NULL) { fprintf(stderr, "%s: Unknown lwsrv argument %s\n", myname, str); exit(1); } return(sp->flags); } static char * keyname(str) char *str; { register struct descrip *sp; if (strcmp(str, includename) == 0) return("Include"); if (oldformat) return(str); return((sp = (struct descrip *)SearchKVTree(argname, str, strcmp)) ? sp->name : str); } #define DQUOTE (1 << 0) #define SQUOTE (1 << 1) static char * quotestr(str) register char *str; { static char buf[256]; register char *fp, *tp, *bp; register int quote; if (!str) return(""); quote = 0; if (index(str, '"')) quote |= DQUOTE; if (index(str, '\'')) quote |= SQUOTE; if (!quote && !index(str, ' ') && !index(str, '\t')) { bp = str; if (index(bp, '\n')) { strcpy(bp = buf, str); if (fp = index(bp, '\n')) *fp = 0; } if (strlen(bp) == 2 && *bp == '-' && isalpha(bp[1])) { sprintf(buf, "\"-%c\"", bp[1]); bp = buf; } return(bp); } switch(quote) { case 0: case (DQUOTE | SQUOTE): quote = '"'; break; default: quote = (quote & SQUOTE) ? '"' : '\''; break; } fp = str; tp = buf; *tp++ = quote; while (*fp) { if (*fp == '\n') { fp++; continue; } if (*fp == quote) *tp++ = quote; *tp++ = *fp++; } *tp++ = quote; *tp = 0; return(buf); } static void setfirsttime(str) register char *str; { while (*str) firsttime[*str++] = 1; } static unshort * ushortdup(i) int i; { register unshort *sp; if ((sp = (unshort *)malloc(sizeof(unshort))) == NULL) errorexit(1, "ushortdup: Out of memory\n"); *sp = i; return(sp); } #if (!(defined(SOLARIS)||defined(bsdi)||defined(__NetBSD__)||defined(__FreeBSD__)||defined(linux))) char * strdup(str) char *str; { register char *cp; if ((cp = (char *)malloc(strlen(str) + 1)) == NULL) errorexit(1, "strdup: Out of memory\n"); strcpy(cp, str); return(cp); } #endif /* SOLARIS || bsdi || __NetBSD__ */ static void usage() { fprintf(stderr, "Usage: %s [-l] dbname [-o] [-v] [file]\n", myname); fprintf(stderr, " %s -c newdbname [-o] [-v] [file]\n", myname); exit(1); } static char * untab(str) char *str; { register char *cp, *bp; register int i; static char buf[256]; if (!(bp = index(str, '\t'))) return(keyname(str)); strncpy(buf, str, (i = bp - str)); buf[i] = 0; if ((cp = keyname(str)) != str) strcpy(buf, cp); strcat(buf, " "); strcat(buf, quotestr(bp + 1)); return(buf); }