371 lines
9.4 KiB
C
371 lines
9.4 KiB
C
/*
|
|
(c) Copyright 1996 Hewlett-Packard Company
|
|
(c) Copyright 1996 International Business Machines Corp.
|
|
(c) Copyright 1996 Sun Microsystems, Inc.
|
|
(c) Copyright 1996 Novell, Inc.
|
|
(c) Copyright 1996 Digital Equipment Corp.
|
|
(c) Copyright 1996 Fujitsu Limited
|
|
(c) Copyright 1996 Hitachi, Ltd.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the names of the copyright holders shall
|
|
not be used in advertising or otherwise to promote the sale, use or other
|
|
dealings in this Software without prior written authorization from said
|
|
copyright holders.
|
|
*/
|
|
|
|
/* To get the tempnam() prototype in <stdio.h> */
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#if defined(linux) && defined(__STRICT_ANSI__)
|
|
#undef __STRICT_ANSI__
|
|
#endif
|
|
|
|
#include <X11/Xos.h> /* for unistd.h and string.h */
|
|
#include <stdio.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
#include "misc.h"
|
|
#include "dixstruct.h"
|
|
|
|
#include <X11/extensions/Print.h>
|
|
|
|
#include "attributes.h"
|
|
|
|
#define IN_FILE_STRING "%(InFile)%"
|
|
#define OUT_FILE_STRING "%(OutFile)%"
|
|
|
|
/*
|
|
* ReplaceAnyString returns a string combining the input strings.
|
|
* It replaces all occurances of 'target' with the supplied
|
|
* 'replacement'.
|
|
* The original input string will generally be freed,
|
|
* and the caller is responsible for freeing whatever string is returned.
|
|
*/
|
|
char *
|
|
ReplaceAnyString(
|
|
char *string,
|
|
char *target,
|
|
char *replacement)
|
|
{
|
|
char *pKeyString;
|
|
|
|
if(replacement != (char *)NULL)
|
|
{
|
|
while((pKeyString = strstr(string, target)) != (char *)NULL)
|
|
{
|
|
char *newString;
|
|
|
|
newString = (char *)xalloc(strlen(string) + strlen(replacement) -
|
|
strlen(target) + 1);
|
|
strncpy(newString, string, pKeyString - string);
|
|
newString[pKeyString - string] = '\0';
|
|
strcat(newString, replacement);
|
|
strcat(newString, pKeyString + strlen(target));
|
|
xfree(string);
|
|
string = newString;
|
|
}
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
/*
|
|
* ReplaceFileString returns a string combining the input strings.
|
|
* It replaces all occurances of IN_FILE_STRING with the supplied
|
|
* inFileName, and all occurances of OUT_FILE_STRING with the
|
|
* supplied outFileName. The original input string will generally be freed,
|
|
* and the caller is responsible for freeing whatever string is returned.
|
|
*/
|
|
char *
|
|
ReplaceFileString(
|
|
char *string,
|
|
char *inFileName,
|
|
char *outFileName)
|
|
{
|
|
char *pKeyString,
|
|
*pInFileString = IN_FILE_STRING,
|
|
*pOutFileString = OUT_FILE_STRING;
|
|
|
|
if(inFileName != (char *)NULL)
|
|
{
|
|
while((pKeyString = strstr(string, pInFileString)) !=
|
|
(char *)NULL)
|
|
{
|
|
char *newString;
|
|
|
|
newString = (char *)xalloc(strlen(string) +
|
|
strlen(inFileName) + 1);
|
|
strncpy(newString, string, pKeyString - string);
|
|
newString[pKeyString - string] = '\0';
|
|
strcat(newString, inFileName);
|
|
strcat(newString, pKeyString + strlen(pInFileString));
|
|
xfree(string);
|
|
string = newString;
|
|
}
|
|
}
|
|
|
|
if(outFileName != (char *)NULL)
|
|
{
|
|
while((pKeyString = strstr(string, pOutFileString)) !=
|
|
(char *)NULL)
|
|
{
|
|
char *newString;
|
|
|
|
newString = (char *)xalloc(strlen(string) +
|
|
strlen(outFileName) + 1);
|
|
strncpy(newString, string, pKeyString - string);
|
|
newString[pKeyString - string] = '\0';
|
|
strcat(newString, outFileName);
|
|
strcat(newString, pKeyString + strlen(pOutFileString));
|
|
xfree(string);
|
|
string = newString;
|
|
}
|
|
}
|
|
return string;
|
|
}
|
|
|
|
|
|
/*
|
|
* TransferBytes reads numBytes of data from pSrcFile and writes them
|
|
* to pDstFile. It returns the number of bytes actually transfered,
|
|
* which will be numBytes if it's successful. Neither pSrcFile nor
|
|
* pDstFile are rewound or their pointers otherwise modified prior to
|
|
* beginning the transfer.
|
|
*/
|
|
int
|
|
TransferBytes(
|
|
FILE *pSrcFile,
|
|
FILE *pDstFile,
|
|
int numBytes)
|
|
{
|
|
char buf[10240];
|
|
#define BUF_SIZE (sizeof(buf)*sizeof(char))
|
|
int bytesWritten = 0;
|
|
unsigned bytesToXfer;
|
|
|
|
for(bytesToXfer = min(BUF_SIZE, (unsigned)numBytes);
|
|
bytesToXfer > 0;
|
|
bytesToXfer = min(BUF_SIZE, (unsigned)(numBytes - bytesWritten)))
|
|
{
|
|
if(fread((void *)buf, (size_t) 1, bytesToXfer, pSrcFile) < bytesToXfer)
|
|
return bytesWritten;
|
|
if(fwrite((void *)buf, (size_t) 1, bytesToXfer, pDstFile) < bytesToXfer)
|
|
return bytesWritten;
|
|
bytesWritten += bytesToXfer;
|
|
}
|
|
return bytesWritten;
|
|
}
|
|
|
|
/*
|
|
* CopyContentsAndDelete - does the work of copying and deleting the
|
|
* pre, no, and post raster files as well as the raster file itself.
|
|
*/
|
|
Bool
|
|
CopyContentsAndDelete(
|
|
FILE **ppSrcFile,
|
|
char **pSrcFileName,
|
|
FILE *pDstFile)
|
|
{
|
|
struct stat statBuf;
|
|
|
|
if(stat(*pSrcFileName, &statBuf) < 0)
|
|
return FALSE;
|
|
rewind(*ppSrcFile);
|
|
if(TransferBytes(*ppSrcFile, pDstFile,
|
|
(int)statBuf.st_size) != (int)statBuf.st_size)
|
|
return FALSE;
|
|
fclose(*ppSrcFile);
|
|
*ppSrcFile = (FILE *)NULL;
|
|
unlink(*pSrcFileName);
|
|
xfree(*pSrcFileName);
|
|
*pSrcFileName = (char *)NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#define QUADPAD(x) ((((x)+3)>>2)<<2)
|
|
|
|
int
|
|
XpSendDocumentData(
|
|
ClientPtr client,
|
|
FILE *fp,
|
|
int fileLen,
|
|
int maxBufSize)
|
|
{
|
|
xPrintGetDocumentDataReply *pRep;
|
|
int bytesWritten;
|
|
unsigned bytesToWrite;
|
|
int result = Success;
|
|
|
|
if(client->clientGone)
|
|
return Success;
|
|
|
|
pRep = (xPrintGetDocumentDataReply *)xalloc(sz_xPrintGetDocumentDataReply+
|
|
QUADPAD(maxBufSize));
|
|
|
|
for(bytesToWrite = min(maxBufSize, fileLen),
|
|
bytesWritten = 0;
|
|
bytesToWrite > 0;
|
|
bytesToWrite = min(maxBufSize, fileLen - bytesWritten))
|
|
{
|
|
pRep->type = X_Reply;
|
|
pRep->sequenceNumber = client->sequence;
|
|
pRep->length = (QUADPAD(bytesToWrite)) >> 2;
|
|
pRep->dataLen = bytesToWrite;
|
|
|
|
if(fread((void *)(pRep + 1), 1, bytesToWrite, fp) < bytesToWrite)
|
|
{
|
|
result = BadAlloc; /* XXX poor error choice? */
|
|
pRep->statusCode = 2; /* XXX Is this the right value??? */
|
|
}
|
|
else
|
|
pRep->statusCode = 0; /* XXX Ignored??? */
|
|
|
|
pRep->finishedFlag = FALSE;
|
|
|
|
if (client->swapped) {
|
|
int n;
|
|
long l;
|
|
|
|
swaps(&pRep->sequenceNumber, n);
|
|
swapl(&pRep->length, l);
|
|
swapl(&pRep->statusCode, l); /* XXX Why are these longs??? */
|
|
swapl(&pRep->finishedFlag, l); /* XXX Why are these longs??? */
|
|
swapl(&pRep->dataLen, l);
|
|
}
|
|
|
|
(void)WriteToClient(client,
|
|
sz_xPrintGetDocumentDataReply + bytesToWrite,
|
|
(char *)pRep);
|
|
bytesWritten += bytesToWrite;
|
|
}
|
|
|
|
xfree(pRep);
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* XpFinishDocData - send a DocumentData reply with the "finishedFlag"
|
|
* field set to TRUE. This routine should be called from the EndJob
|
|
* function of a driver after the driver has sent all required
|
|
* document data (presumably via XpSendDocumentData).
|
|
*/
|
|
int
|
|
XpFinishDocData(
|
|
ClientPtr client)
|
|
{
|
|
xPrintGetDocumentDataReply rep;
|
|
|
|
if(client->clientGone)
|
|
return Success;
|
|
|
|
rep.type = X_Reply;
|
|
rep.sequenceNumber = client->sequence;
|
|
rep.length = 0;
|
|
rep.dataLen = 0;
|
|
rep.finishedFlag = TRUE;
|
|
rep.statusCode = 0;
|
|
|
|
if (client->swapped) {
|
|
int n;
|
|
long l;
|
|
|
|
swaps(&rep.sequenceNumber, n);
|
|
swapl(&rep.length, l);
|
|
swapl(&rep.statusCode, l); /* XXX Why are these longs??? */
|
|
swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */
|
|
swapl(&rep.dataLen, l);
|
|
}
|
|
|
|
(void)WriteToClient(client, sz_xPrintGetDocumentDataReply, (char *)&rep);
|
|
return Success;
|
|
}
|
|
|
|
#ifndef HAVE_MKSTEMP
|
|
static
|
|
char *XpDirName(char *fname)
|
|
{
|
|
char *fn, *ptr;
|
|
|
|
fn = (char *)xalloc(strlen(fname) + 1);
|
|
if (fn) {
|
|
strcpy(fn, fname);
|
|
ptr = strrchr(fn, '/');
|
|
if (!ptr) {
|
|
ptr = fn;
|
|
*ptr++ = '.';
|
|
} else if (ptr == fn)
|
|
ptr++;
|
|
*ptr = '\0';
|
|
}
|
|
return fn;
|
|
}
|
|
#endif
|
|
|
|
Bool
|
|
XpOpenTmpFile(
|
|
char *mode,
|
|
char **fname,
|
|
FILE **stream)
|
|
{
|
|
#ifndef HAVE_MKSTEMP
|
|
char *fn = NULL;
|
|
|
|
/* note that there is a small race condition here... */
|
|
if (!(*fname = tempnam(NULL, NULL)) ||
|
|
!(fn = XpDirName(*fname)) ||
|
|
access(fn, W_OK) ||
|
|
!(*stream = fopen(*fname, mode)))
|
|
|
|
{
|
|
xfree(fn);
|
|
xfree(*fname);
|
|
*fname = NULL;
|
|
*stream = NULL;
|
|
return FALSE;
|
|
}
|
|
xfree(fn);
|
|
#else
|
|
int fd;
|
|
|
|
*stream = NULL;
|
|
*fname = (char *)xalloc(14);
|
|
if (*fname == NULL)
|
|
return FALSE;
|
|
strcpy(*fname, "/tmp/xpXXXXXX");
|
|
fd = mkstemp(*fname);
|
|
if (fd < 0) {
|
|
xfree(*fname);
|
|
*fname = NULL;
|
|
return FALSE;
|
|
}
|
|
*stream = fdopen(fd, mode);
|
|
if (stream == NULL) {
|
|
xfree(*fname);
|
|
*fname = NULL;
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|