#include <X11/Xproto.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pwd.h>
#if (defined(sun) && defined(SVR4)) || (defined(SCO))
#include <wchar.h>
#endif
#include "scrnintstr.h"
#include <X11/extensions/Printstr.h>
#include "attributes.h"
#include "Xlib.h"
#include "Xresource.h"
#include "Xrm.c"
static XrmDatabase CopyDb(XrmDatabase inDb);
extern XrmDatabase XpSpoolerGetServerAttributes(void);
static unsigned long attrGeneration = 0;
typedef struct {
XrmDatabase *pDb;
char *qualifier;
char *modelId;
} DbEnumStruct;
typedef struct {
char *stringDb;
int nextPos;
int space;
} StringDbStruct;
typedef struct _printerAttrs {
struct _printerAttrs *next;
char *name;
char *qualifier;
XrmDatabase printerAttrs;
XrmDatabase docAttrs;
XrmDatabase jobAttrs;
} PrAttrs, *PrAttrPtr;
static PrAttrPtr attrList = (PrAttrPtr)NULL;
typedef struct _systemAttrs {
XrmDatabase doc;
XrmDatabase job;
XrmDatabase printers;
XrmDatabase server;
} SysAttrs, *SysAttrsPtr;
SysAttrs systemAttributes;
static int attrCtxtPrivIndex;
typedef struct _contextAttrs {
XrmDatabase printerAttrs;
XrmDatabase docAttrs;
XrmDatabase jobAttrs;
XrmDatabase pageAttrs;
} ContextAttrs, *ContextAttrPtr;
static const char XPDIR[] = "/print";
static const char XPPRINTERATTRFILE[] = "/attributes/printer";
static const char XPJOBATTRFILE[] = "/attributes/job";
static const char XPDOCATTRFILE[] = "/attributes/document";
static const char XPMODELDIR[] = "/models";
static char NULL_STRING[] = "\0";
char *
XpGetConfigDir(Bool useLocale)
{
char *dirName, *langName, *langDir, *configDir;
Bool freeLangDir = False;
if(useLocale == False) langDir = "/C";
else
{
if((langName = getenv("LANG")) == (char *)NULL)
return (char *)NULL;
else
{
if(strcmp(langName, "C") == 0)
return (char *)NULL;
langDir = (char *)xalloc(strlen(langName) + 2);
sprintf(langDir, "/%s", langName);
freeLangDir = True;
}
}
if((configDir = getenv("XPCONFIGDIR")) == (char *)NULL)
configDir = XPRINTDIR;
dirName = (char *)xalloc(strlen(configDir) + strlen(XPDIR) +
strlen(langDir) + 1);
sprintf(dirName, "%s%s%s", configDir, langDir, XPDIR);
if(freeLangDir == True)
xfree(langDir);
return dirName;
}
static XrmDatabase
GetMergedDatabase(const char *attrName)
{
char *dirName, *fileName;
XrmDatabase db;
if((dirName = XpGetConfigDir(False)) == (char *)NULL)
return (XrmDatabase)NULL;
if((fileName = (char *)xalloc(strlen(dirName) + strlen(attrName) + 1)) ==
(char *)NULL)
return (XrmDatabase)NULL;
sprintf(fileName, "%s%s", dirName, attrName);
db = XrmGetFileDatabase(fileName);
xfree(fileName);
xfree(dirName);
if((dirName = XpGetConfigDir(True)) == (char *)NULL)
return db;
if((fileName = (char *)xalloc(strlen(dirName) + strlen(attrName) + 1)) ==
(char *)NULL)
return db;
sprintf(fileName, "%s%s", dirName, attrName);
(void)XrmCombineFileDatabase(fileName, &db, True);
xfree(fileName);
xfree(dirName);
return db;
}
static void
BuildSystemAttributes(void)
{
if(systemAttributes.printers != (XrmDatabase)NULL)
XrmDestroyDatabase(systemAttributes.printers);
systemAttributes.printers = GetMergedDatabase(XPPRINTERATTRFILE);
if(systemAttributes.job != (XrmDatabase)NULL)
XrmDestroyDatabase(systemAttributes.job);
systemAttributes.job = GetMergedDatabase(XPJOBATTRFILE);
if(systemAttributes.doc != (XrmDatabase)NULL)
XrmDestroyDatabase(systemAttributes.doc);
systemAttributes.doc = GetMergedDatabase(XPDOCATTRFILE);
if(systemAttributes.server != (XrmDatabase)NULL)
XrmDestroyDatabase(systemAttributes.server);
systemAttributes.server = XpSpoolerGetServerAttributes();
return;
}
static Bool
AddDbEntry(
XrmDatabase *sourceDB,
XrmBindingList bindings,
XrmQuarkList quarks,
XrmRepresentation *type,
XrmValue *value,
XPointer client_data)
{
DbEnumStruct *pEnumStruct = (DbEnumStruct *)client_data;
XrmName xrm_name[5];
XrmClass xrm_class[5];
XrmBinding xrm_bind[3];
XrmValue realVal;
XrmRepresentation rep_type;
xrm_name[0] = XrmStringToQuark (pEnumStruct->qualifier);
xrm_class[0] = XrmStringToQuark (pEnumStruct->modelId);
for(;*quarks; quarks++)
xrm_name[1] = xrm_class[1] = *quarks;
xrm_name[2] = (XrmQuark)NULL;
xrm_class[2] = (XrmQuark)NULL;
if(XrmQGetResource (*sourceDB, xrm_name, xrm_class, &rep_type, &realVal))
{
xrm_bind[0] = XrmBindLoosely;
xrm_name[0] = xrm_name[1];
xrm_name[1] = NULLQUARK;
XrmQPutStringResource(pEnumStruct->pDb, xrm_bind, xrm_name,
(char *)realVal.addr);
}
return FALSE;
}
static XrmDatabase
BuildPrinterAttrs(
char *printerName,
char *qualifierName)
{
XrmDatabase printerDB = (XrmDatabase)NULL;
if(systemAttributes.printers != (XrmDatabase)NULL)
{
char *fileName;
XrmDatabase modelDB = (XrmDatabase)NULL;
XrmName xrm_name[5], xrm_class[2];
XrmRepresentation rep_type;
XrmValue value;
DbEnumStruct enumStruct;
Bool freeModelDB = False;
xrm_name[0] = XrmStringToQuark (qualifierName);
xrm_name[1] = XrmStringToQuark ("xp-model-identifier");
xrm_name[2] = (XrmQuark)NULL;
XrmQGetResource (systemAttributes.printers, xrm_name, xrm_name,
&rep_type, &value);
if(value.addr != (XPointer)NULL)
{
fileName = (char *)xalloc(strlen(XPMODELDIR) +
strlen((char *)value.addr) +
strlen("model-config") + 3);
sprintf(fileName, "%s/%s/%s", XPMODELDIR, value.addr,
"model-config");
modelDB = GetMergedDatabase(fileName);
xfree(fileName);
if(modelDB != (XrmDatabase)NULL)
{
XrmDatabase tempDB = (XrmDatabase)NULL;
tempDB = CopyDb(systemAttributes.printers);
XrmMergeDatabases(tempDB, &modelDB);
freeModelDB = True;
}
}
if(modelDB == (XrmDatabase)NULL)
modelDB = systemAttributes.printers;
xrm_name[0] = XrmStringToQuark (qualifierName);
xrm_name[1] = (XrmQuark)NULL;
xrm_class[0] = XrmStringToQuark((char *)value.addr);
xrm_class[1] = (XrmQuark)NULL;
enumStruct.pDb = &printerDB;
enumStruct.qualifier = (char *)qualifierName;
enumStruct.modelId = (char *)value.addr;
XrmEnumerateDatabase(modelDB, xrm_name, xrm_class, XrmEnumAllLevels,
AddDbEntry, (XPointer) &enumStruct);
if(freeModelDB == True) XrmDestroyDatabase(modelDB);
}
XrmPutStringResource(&printerDB, "*printer-name", printerName);
XrmPutStringResource(&printerDB, "*qualifier", qualifierName);
return printerDB;
}
static XrmDatabase
BuildABase(
char *printerName,
char *qualifierName,
XrmDatabase sourceBase)
{
XrmDatabase builtDB = (XrmDatabase)NULL;
if(sourceBase != (XrmDatabase)NULL)
{
XrmName xrm_name[5], xrm_class[2];
XrmRepresentation rep_type;
XrmValue value;
DbEnumStruct enumStruct;
xrm_name[0] = XrmStringToQuark (printerName);
xrm_name[1] = XrmStringToQuark ("xp-model-identifier");
xrm_name[2] = (XrmQuark)NULL;
XrmQGetResource (systemAttributes.printers, xrm_name, xrm_name,
&rep_type, &value);
if(value.addr != (XPointer)NULL)
xrm_class[0] = XrmStringToQuark((char *)value.addr);
else
xrm_class[0] = xrm_name[0];
xrm_class[1] = (XrmQuark)NULL;
xrm_name[1] = (XrmQuark)NULL;
enumStruct.pDb = &builtDB;
enumStruct.qualifier = (char *)qualifierName;
enumStruct.modelId = (char *)value.addr;
XrmEnumerateDatabase(sourceBase, xrm_name, xrm_class, XrmEnumAllLevels,
AddDbEntry, (XPointer) &enumStruct);
}
XrmPutStringResource(&builtDB, "*qualifier", qualifierName);
return builtDB;
}
static void
FreeAttrList(void)
{
PrAttrPtr pAttr, pNext;
for(pAttr = attrList, pNext = attrList;
pAttr != (PrAttrPtr)NULL;
pAttr = pNext)
{
pNext = pAttr->next;
if(pAttr->printerAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pAttr->printerAttrs);
if(pAttr->docAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pAttr->docAttrs);
if(pAttr->jobAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pAttr->jobAttrs);
xfree(pAttr->name);
xfree(pAttr->qualifier);
xfree(pAttr);
}
attrList = (PrAttrPtr)NULL;
}
int
XpRehashAttributes(void)
{
if(attrList != (PrAttrPtr)NULL)
FreeAttrList();
BuildSystemAttributes();
return Success;
}
void
XpBuildAttributeStore(
char *printerName,
char *qualifierName)
{
PrAttrPtr pAttr;
if((pAttr = (PrAttrPtr)xalloc(sizeof(PrAttrs))) == (PrAttrPtr)NULL)
return;
if(attrGeneration != serverGeneration)
{
if(attrList != (PrAttrPtr)NULL)
FreeAttrList();
attrCtxtPrivIndex = XpAllocateContextPrivateIndex();
XpAllocateContextPrivate(attrCtxtPrivIndex, sizeof(ContextAttrs));
BuildSystemAttributes();
attrGeneration = serverGeneration;
}
if(attrList == (PrAttrPtr)NULL)
{
pAttr->next = (PrAttrPtr)NULL;
attrList = pAttr;
}
else
{
pAttr->next = attrList;
attrList = pAttr;
}
pAttr->name = strdup(printerName);
pAttr->qualifier = strdup(qualifierName);
pAttr->printerAttrs = BuildPrinterAttrs(printerName, qualifierName);
pAttr->docAttrs = BuildABase(printerName, qualifierName,
systemAttributes.doc);
pAttr->jobAttrs = BuildABase(printerName, qualifierName,
systemAttributes.job);
}
static Bool
StoreEntry(
XrmDatabase *sourceDB,
XrmBindingList bindings,
XrmQuarkList quarks,
XrmRepresentation *type,
XrmValue *value,
XPointer client_data)
{
XrmDatabase *outDb = (XrmDatabase *)client_data;
XrmQPutStringResource(outDb, bindings, quarks, (char *)value->addr);
return FALSE;
}
static XrmDatabase
CopyDb(XrmDatabase inDb)
{
XrmDatabase outDb = (XrmDatabase)NULL;
XrmQuark empty = NULLQUARK;
(void)XrmEnumerateDatabase(inDb, &empty, &empty, XrmEnumAllLevels,
StoreEntry, (XPointer) &outDb);
return outDb;
}
void
XpInitAttributes(XpContextPtr pContext)
{
ContextAttrPtr pCtxtAttrs;
PrAttrPtr pPrAttr = attrList;
pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
(void)memset((void *)pCtxtAttrs, 0, (size_t) sizeof(ContextAttrs));
for(pPrAttr = attrList; pPrAttr != (PrAttrPtr)NULL; pPrAttr = pPrAttr->next)
if(!strcmp(pPrAttr->name, pContext->printerName)) break;
if(pPrAttr != (PrAttrPtr)NULL)
{
pCtxtAttrs->printerAttrs = CopyDb(pPrAttr->printerAttrs);
pCtxtAttrs->docAttrs = CopyDb(pPrAttr->docAttrs);
pCtxtAttrs->jobAttrs = CopyDb(pPrAttr->jobAttrs);
}
}
void
XpDestroyAttributes(
XpContextPtr pContext)
{
ContextAttrPtr pCtxtAttrs;
pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
if(pCtxtAttrs->printerAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->printerAttrs);
if(pCtxtAttrs->docAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->docAttrs);
if(pCtxtAttrs->jobAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->jobAttrs);
if(pCtxtAttrs->pageAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->pageAttrs);
}
char *
XpGetOneAttribute(
XpContextPtr pContext,
XPAttributes class,
char *attributeName)
{
ContextAttrPtr pCtxtAttrs;
XrmDatabase db = (XrmDatabase)NULL;
XrmName xrm_name[3];
XrmRepresentation rep_type;
XrmValue value;
if(class == XPServerAttr)
{
if(systemAttributes.server == (XrmDatabase)NULL)
return NULL_STRING;
xrm_name[0] = XrmStringToQuark (attributeName);
xrm_name[1] = (XrmQuark)NULL;
XrmQGetResource(systemAttributes.server, xrm_name, xrm_name,
&rep_type, &value);
if(value.addr == (char *)NULL)
return NULL_STRING;
return (char *)value.addr;
}
else
{
pCtxtAttrs=(ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
switch(class)
{
case XPPrinterAttr:
db = pCtxtAttrs->printerAttrs;
break;
case XPDocAttr:
db = pCtxtAttrs->docAttrs;
break;
case XPJobAttr:
db = pCtxtAttrs->jobAttrs;
break;
case XPPageAttr:
db = pCtxtAttrs->pageAttrs;
break;
default:
break;
}
}
if(db == (XrmDatabase)NULL)
return NULL_STRING;
xrm_name[0] = XrmStringToQuark ("qualifier");
xrm_name[1] = (XrmQuark)NULL;
XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value);
xrm_name[0] = XrmStringToQuark (value.addr);
xrm_name[1] = XrmStringToQuark (attributeName);
xrm_name[2] = (XrmQuark)NULL;
if(XrmQGetResource(db, xrm_name, xrm_name, &rep_type, &value))
return (char *)value.addr;
else
return NULL_STRING;
}
void
XpPutOneAttribute(
XpContextPtr pContext,
XPAttributes class,
const char* attributeName,
const char* value)
{
ContextAttrPtr pCtxtAttrs;
XrmDatabase db;
XrmBinding bindings[1];
XrmQuark quarks[2];
pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
switch(class)
{
case XPPrinterAttr:
db = pCtxtAttrs->printerAttrs;
break;
case XPDocAttr:
db = pCtxtAttrs->docAttrs;
break;
case XPJobAttr:
db = pCtxtAttrs->jobAttrs;
break;
case XPPageAttr:
db = pCtxtAttrs->pageAttrs;
break;
default:
return;
}
bindings[0] = XrmBindLoosely;
quarks[0] = XrmStringToQuark(attributeName);
quarks[1] = (XrmQuark)NULL;
XrmQPutStringResource(&db, bindings, quarks, value ? value : "");
}
static Bool
ExpandSpace(
StringDbStruct *pStr)
{
char *newSpace;
if((newSpace = (char *)xrealloc(pStr->stringDb, pStr->nextPos + pStr->space
+ 1024)) == (char *)NULL)
return False;
pStr->space += 1024;
pStr->stringDb = newSpace;
return True;
}
static void
PutString(
StringDbStruct *pStr,
char *pString)
{
int len = strlen(pString);
if(len >= pStr->space)
if(!ExpandSpace(pStr))
return;
strcpy(&pStr->stringDb[pStr->nextPos], pString);
pStr->nextPos += len;
pStr->space -= len;
}
static void
PutByte(
StringDbStruct *pStr,
char byte)
{
if(pStr->space <= 1)
if(!ExpandSpace(pStr))
return;
pStr->stringDb[pStr->nextPos] = byte;
pStr->nextPos++;
pStr->space--;
}
static Bool
AppendEntry(
XrmDatabase *db,
XrmBindingList bindings,
XrmQuarkList quarks,
XrmRepresentation *type,
XrmValuePtr value,
XPointer data)
{
StringDbStruct *pEnumStr = (StringDbStruct *)data;
Bool firstNameSeen;
unsigned int i;
char *s, c;
if (*type != XrmQString)
return False;
for (firstNameSeen = False; *quarks; bindings++, quarks++) {
if (*bindings == XrmBindLoosely) {
PutString(pEnumStr, "*");
} else if (firstNameSeen) {
PutString(pEnumStr, ".");
}
firstNameSeen = True;
PutString(pEnumStr, XrmQuarkToString(*quarks));
}
s = value->addr;
i = value->size;
PutString(pEnumStr, ":\t");
if(i) i--;
if (i && (*s == ' ' || *s == '\t'))
PutByte(pEnumStr, '\\');
while (i--) {
c = *s++;
if (c == '\n') {
if (i)
PutString(pEnumStr, "\\n\\\n");
else
PutString(pEnumStr, "\\n");
} else if (c == '\\')
PutString(pEnumStr, "\\\\");
else if ((c < ' ' && c != '\t') ||
((unsigned char)c >= 0x7f && (unsigned char)c < 0xa0))
{
char temp[4];
(void) sprintf(temp, "\\%03o", (unsigned char)c);
PutString(pEnumStr, temp);
}
else
PutByte(pEnumStr, c);
}
PutByte(pEnumStr, '\n');
pEnumStr->stringDb[pEnumStr->nextPos] = (char)'\0';
return False;
}
char *
XpGetAttributes(
XpContextPtr pContext,
XPAttributes class)
{
ContextAttrPtr pCtxtAttrs;
XrmDatabase db = (XrmDatabase)NULL;
StringDbStruct enumStruct;
XrmQuark empty = NULLQUARK;
if(class == XPServerAttr)
db = systemAttributes.server;
else
{
pCtxtAttrs=(ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
switch(class)
{
case XPServerAttr:
db = systemAttributes.server;
break;
case XPPrinterAttr:
db = pCtxtAttrs->printerAttrs;
break;
case XPDocAttr:
db = pCtxtAttrs->docAttrs;
break;
case XPJobAttr:
db = pCtxtAttrs->jobAttrs;
break;
case XPPageAttr:
db = pCtxtAttrs->pageAttrs;
break;
default:
break;
}
}
if(db == (XrmDatabase)NULL)
{
char *retval = (char *)xalloc(1);
retval[0] = (char)'\0';
return retval;
}
if((enumStruct.stringDb = (char *)xalloc(1024)) == (char *)NULL)
return (char *)NULL;
enumStruct.stringDb[0] = (char)'\0';
enumStruct.nextPos = 0;
enumStruct.space = 1024;
(void)XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels,
AppendEntry, (XPointer) &enumStruct);
return enumStruct.stringDb;
}
int
XpAugmentAttributes(
XpContextPtr pContext,
XPAttributes class,
char *attributes)
{
XrmDatabase db;
ContextAttrPtr pCtxtAttrs;
db = XrmGetStringDatabase(attributes);
if(db == (XrmDatabase)NULL) return BadAlloc;
pCtxtAttrs = (ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
switch(class)
{
case XPPrinterAttr:
XrmMergeDatabases(db, &pCtxtAttrs->printerAttrs);
break;
case XPDocAttr:
XrmMergeDatabases(db, &pCtxtAttrs->docAttrs);
break;
case XPJobAttr:
XrmMergeDatabases(db, &pCtxtAttrs->jobAttrs);
break;
case XPPageAttr:
XrmMergeDatabases(db, &pCtxtAttrs->pageAttrs);
break;
default:
break;
}
return Success;
}
int
XpSetAttributes(
XpContextPtr pContext,
XPAttributes class,
char *attributes)
{
XrmDatabase db;
ContextAttrPtr pCtxtAttrs;
db = XrmGetStringDatabase(attributes);
if(db == (XrmDatabase)NULL) return BadAlloc;
pCtxtAttrs=(ContextAttrPtr)pContext->devPrivates[attrCtxtPrivIndex].ptr;
switch(class)
{
case XPPrinterAttr:
if(pCtxtAttrs->printerAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->printerAttrs);
pCtxtAttrs->printerAttrs = db;
break;
case XPDocAttr:
if(pCtxtAttrs->docAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->docAttrs);
pCtxtAttrs->docAttrs = db;
break;
case XPJobAttr:
if(pCtxtAttrs->jobAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->jobAttrs);
pCtxtAttrs->jobAttrs = db;
break;
case XPPageAttr:
if(pCtxtAttrs->pageAttrs != (XrmDatabase)NULL)
XrmDestroyDatabase(pCtxtAttrs->pageAttrs);
pCtxtAttrs->pageAttrs = db;
break;
default:
break;
}
return Success;
}
void
XpAddPrinterAttribute(
char *printerName,
char *printerQualifier,
char *attributeName,
char *attributeValue)
{
PrAttrPtr pAttr;
for(pAttr = attrList; pAttr != (PrAttrPtr)NULL; pAttr = pAttr->next)
{
if(!strcmp(printerQualifier, pAttr->qualifier))
{
XrmPutStringResource(&pAttr->printerAttrs, attributeName,
attributeValue);
break;
}
}
}
const char *
XpGetPrinterAttribute(const char *printerName,
const char *attribute)
{
PrAttrPtr pAttr;
XrmValue value;
char *type;
for(pAttr = attrList; pAttr != (PrAttrPtr)NULL; pAttr = pAttr->next)
{
if(!strcmp(printerName, pAttr->qualifier))
{
char *attrStr;
attrStr = (char *)xalloc(strlen(printerName) + strlen(attribute) +
2);
sprintf(attrStr, "%s.%s", printerName, attribute);
XrmGetResource(pAttr->printerAttrs, attrStr, attrStr,
&type, &value);
xfree(attrStr);
break;
}
}
if(value.addr != (XPointer)NULL && strlen(value.addr) != 0)
return value.addr;
else
return "";
}
#include <locale.h>
static char serverAttrStr[] = "*document-attributes-supported: copy-count\n\
*job-attributes-supported: job-name job-owner\
notification-profile xp-spooler-command-options\n\
*multiple-documents-supported: False";
XrmDatabase
XpSpoolerGetServerAttributes(void)
{
char *totalAttrs, *localeName;
XrmDatabase db;
localeName = setlocale(LC_CTYPE, (char *)NULL);
if(!localeName || strlen(localeName) == 0)
localeName = "C";
if((totalAttrs = (char *)xalloc(strlen(serverAttrStr) + strlen(localeName)
+ 11)) == (char *)NULL)
return (XrmDatabase)NULL;
sprintf(totalAttrs, "%s\n%s\t%s", serverAttrStr, "*locale:", localeName);
db = XrmGetStringDatabase(totalAttrs);
xfree(totalAttrs);
return db;
}
static void
SendFileToCommand(
char *fileName,
char *pCommand,
char **argVector,
char *userName)
{
pid_t childPid;
int pipefd[2];
int status;
struct stat statBuf;
FILE *fp, *outPipe;
if(pipe(pipefd))
return;
if(stat(fileName, &statBuf) < 0 || (int)statBuf.st_size == 0)
{
close(pipefd[0]);
close(pipefd[1]);
return;
}
fp = fopen(fileName, "r");
if(fp == (FILE *)NULL)
{
close(pipefd[0]);
close(pipefd[1]);
return;
}
if((childPid = fork()) == 0)
{
close(pipefd[1]);
close(0);
dup(pipefd[0]);
close(pipefd[0]);
if(userName)
{
if(geteuid() == (uid_t)0)
{
struct passwd *pPasswd;
if((pPasswd = getpwnam(userName)))
{
setuid((uid_t)pPasswd->pw_uid);
}
}
}
if (execv(pCommand, argVector) == -1) {
FatalError("unable to exec '%s'", pCommand);
}
}
else
{
(void) close(pipefd[0]);
outPipe = fdopen(pipefd[1], "w");
(void) TransferBytes(fp, outPipe, (int)statBuf.st_size);
(void) fclose(outPipe);
(void) fclose(fp);
(void) waitpid(childPid, &status, 0);
}
return;
}
static char *
ReplaceAllKeywords(
XpContextPtr pContext,
char *command)
{
char *cmdOpt;
cmdOpt = XpGetOneAttribute(pContext, XPPrinterAttr,
"xp-spooler-printer-name");
if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0)
command = ReplaceAnyString(command, "%printer-name%", cmdOpt);
else
command = ReplaceAnyString(command, "%printer-name%",
pContext->printerName);
cmdOpt = XpGetOneAttribute(pContext, XPDocAttr, "copy-count");
if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0)
command = ReplaceAnyString(command, "%copy-count%", cmdOpt);
else
command = ReplaceAnyString(command, "%copy-count%", "1");
cmdOpt = XpGetOneAttribute(pContext, XPJobAttr, "job-name");
if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0)
command = ReplaceAnyString(command, "%job-name%", cmdOpt);
else
command = ReplaceAnyString(command, "%job-name%", "");
cmdOpt = XpGetOneAttribute(pContext, XPJobAttr, "job-owner");
if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0)
command = ReplaceAnyString(command, "%job-owner%", cmdOpt);
else
command = ReplaceAnyString(command, "%job-owner%", "");
cmdOpt = XpGetOneAttribute(pContext, XPJobAttr,
"xp-spooler-command-options");
if(cmdOpt != (char *)NULL && strlen(cmdOpt) != 0)
command = ReplaceAnyString(command, "%options%", cmdOpt);
else
command = ReplaceAnyString(command, "%options%", "");
return command;
}
#ifdef __QNX__
#define toascii( c ) ((unsigned)(c) & 0x007f)
#endif
#if defined(CSRG_BASED) || \
defined(linux) || \
defined(__CYGWIN__) || \
(defined(sun) && !defined(SVR4)) || \
(defined(SVR4) && !defined(sun) && !defined(USL)) || \
defined(__UNIXOS2__) || \
defined(ISC) || \
defined(Lynx) || \
defined(__QNX__) || \
defined(__DARWIN__)
#define iswspace(c) (isascii(c) && isspace(toascii(c)))
#endif
static int
GetToken(
char *inStr,
char **outStr)
{
size_t mbCurMax = MB_CUR_MAX;
wchar_t curChar;
int i, numBytes, byteLen = strlen(inStr);
char *tok;
for(i = 0, numBytes = 0; i < byteLen; i += numBytes)
{
numBytes = mbtowc(&curChar, &inStr[i], mbCurMax);
if(!iswspace(curChar))
break;
}
tok = inStr + i;
byteLen = strlen(tok);
for(i = 0, numBytes = 0; i < byteLen; i += numBytes)
{
numBytes = mbtowc(&curChar, &tok[i], mbCurMax);
if(iswspace(curChar))
break;
}
if((*outStr = (char *)xalloc(i + 1)) == (char *)NULL)
return 0;
strncpy(*outStr, tok, i);
(*outStr)[i] = (char)'\0';
return (tok + i) - inStr;
}
static void
FreeVector(
char **vector)
{
int i;
if(vector == (char **)NULL) return;
for(i = 0; vector[i] != (char *)NULL; i++)
xfree(vector[i]);
xfree(vector);
}
static void
AddVector(
char ***pTarget,
char **pAddition)
{
int numTarget, numAdd, i;
for(numTarget = 0; (*pTarget)[numTarget] != (char *)NULL; numTarget++)
;
for(numAdd = 0; pAddition[numAdd] != (char *)NULL; numAdd++)
;
*pTarget = (char **)xrealloc((void *)*pTarget, (numTarget + numAdd + 1) *
sizeof(char *));
if(*pTarget == (char **)NULL)
return;
for(i = 0; i < numAdd; i++)
(*pTarget)[numTarget + i] = pAddition[i];
(*pTarget)[numTarget + numAdd] = (char *)NULL;
}
static char **
BuildArgVector(
char *argString,
XpContextPtr pContext)
{
char **pVector;
char *curTok;
int numChars, i;
static int beenHere = 0;
pVector = (char **)xalloc(sizeof(char *));
pVector[0] = (char *)NULL;
for(i = 0; (numChars = GetToken(argString, &curTok)) != 0;
i++, argString += numChars)
{
if(beenHere || strcmp(curTok, "%options%"))
{
if(curTok[0] == (char)'\0')
{
xfree(curTok);
}
else
{
pVector = (char **)xrealloc((void *)pVector,
(i + 2)*sizeof(char *));
if(pVector == (char **)NULL)
return (char **)NULL;
pVector[i] = curTok;
pVector[i + 1] = (char *)NULL;
}
}
else if(!beenHere)
{
char **optionsVec;
curTok = ReplaceAllKeywords(pContext, curTok);
beenHere = 1;
optionsVec = BuildArgVector(curTok, pContext);
xfree(curTok);
beenHere = 0;
AddVector(&pVector, optionsVec);
xfree(optionsVec);
}
}
if(numChars == 0 && curTok != (char *)NULL)
xfree(curTok);
return pVector;
}
static char *
VectorizeCommand(
char *command,
char ***pVector,
XpContextPtr pContext)
{
char *cmdName;
if(command == (char *)NULL)
return (char *)NULL;
(void) GetToken(command, &cmdName);
if(cmdName == (char *)NULL)
return (char *)NULL;
*pVector = BuildArgVector(command, pContext);
return cmdName;
}
#ifdef hpux
static char DEFAULT_SPOOL_COMMAND[] = "/usr/bin/lp -d %printer-name% -o raw -n %copy-count% -t %job-name% %options%";
#else
static char DEFAULT_SPOOL_COMMAND[] = "/usr/bin/lp -d %printer-name% -n %copy-count% -t %job-name% %options%";
#endif
int
XpSubmitJob(
char *fileName,
XpContextPtr pContext)
{
char **vector, *cmdNam, *command, *userName;
int i;
command = XpGetOneAttribute(pContext, XPPrinterAttr, "xp-spooler-command");
if(command == (char *)NULL || strlen(command) == 0)
command = strdup(DEFAULT_SPOOL_COMMAND);
else
command = strdup(command);
if(command == (char *)NULL)
return BadAlloc;
cmdNam = VectorizeCommand(command, &vector, pContext);
xfree(command);
if(cmdNam == (char *)NULL)
return BadAlloc;
for(i = 0; vector[i] != (char *)NULL; i++)
{
vector[i] = ReplaceAllKeywords(pContext, vector[i]);
if(vector[i] == (char *)NULL)
{
xfree(cmdNam);
for(i = 0; vector[i] != (char *)NULL; i++)
xfree(vector[i]);
xfree(vector);
return BadAlloc;
}
}
userName = XpGetOneAttribute(pContext, XPJobAttr, "job-owner");
if(userName != (char *)NULL && strlen(userName) == 0)
userName = (char *)NULL;
SendFileToCommand(fileName, cmdNam, vector, userName);
FreeVector(vector);
xfree(cmdNam);
return Success;
}
#define TRAY 0
#define MEDIUM 1
static char *
SearchInputTrays(XpContextPtr pCon,
int which,
char *val)
{
char *inputTraysMedium, tray[80], medium[80], *copy;
char *pS, *pE, *pLast;
inputTraysMedium = XpGetOneAttribute( pCon, XPPrinterAttr,
"input-trays-medium" );
copy = strdup( inputTraysMedium );
pS = copy;
pLast = copy + strlen( copy );
while( pS < pLast )
{
while( *pS && *pS != '{' )
pS++;
pE = ++pS;
while( *pE && *pE != '}' )
pE++;
*pE = '\0';
sscanf( pS, "%s %s", tray, medium );
if( which == MEDIUM && !strcmp( val, medium ) )
{
xfree( copy );
return strdup( tray );
}
if( which == TRAY && !strcmp( val, tray ) )
{
xfree( copy );
return strdup( medium );
}
pS = pE + 1;
}
xfree( copy );
return strdup( NULL_STRING );
}
void
XpGetTrayMediumFromContext(XpContextPtr pCon,
char **medium,
char **tray)
{
char *defMedium, *defTray;
char *t, *m;
defMedium = XpGetOneAttribute( pCon, XPPageAttr,
"default-medium" );
if( *defMedium == '\0' )
defMedium = XpGetOneAttribute( pCon, XPDocAttr,
"default-medium" );
defTray = XpGetOneAttribute( pCon, XPPageAttr,
"default-input-tray" );
if( *defTray == '\0' )
defTray = XpGetOneAttribute( pCon, XPDocAttr,
"default-input-tray" );
m = SearchInputTrays( pCon, TRAY, defTray );
if( !strcmp( m, defMedium ) )
{
xfree( m );
*tray = strdup( defTray );
*medium = strdup( defMedium );
return;
}
t = SearchInputTrays( pCon, MEDIUM, defMedium );
if( t )
{
*tray = t;
*medium = strdup( defMedium );
return;
}
*tray = strdup( defTray );
*medium = m;
xfree( t );
}