summaryrefslogtreecommitdiff
path: root/Xprint/Util.c
diff options
context:
space:
mode:
Diffstat (limited to 'Xprint/Util.c')
-rw-r--r--Xprint/Util.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/Xprint/Util.c b/Xprint/Util.c
new file mode 100644
index 000000000..efc196f82
--- /dev/null
+++ b/Xprint/Util.c
@@ -0,0 +1,360 @@
+/* $Xorg: Util.c,v 1.3 2000/08/17 19:48:06 cpqbld Exp $ */
+/*
+(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.
+*/
+#include "Xos.h" /* for unistd.h and string.h */
+#include <stdio.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include "dixstruct.h"
+#include "scrnintstr.h"
+#include "misc.h"
+
+#define _XP_PRINT_SERVER_
+#include "extensions/Print.h"
+#include "extensions/Printstr.h"
+#undef _XP_PRINT_SERVER_
+
+#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(string, inFileName, outFileName)
+ 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;
+}
+
+/*
+ * ExecCommand takes two character pointers - the command to execute,
+ * and the "argv" style NULL-terminated vector of arguments for the command.
+ * We wait for the command to terminate before continuing to ensure that
+ * we don't delete the job file before the spooler has made a copy.
+ */
+void
+ExecCommand(pCommand, argVector)
+ char *pCommand;
+ char **argVector;
+{
+ pid_t childPid;
+ int status;
+
+ if((childPid = fork()) == 0)
+ {
+ execv(pCommand, argVector);
+ }
+ else
+ {
+ (void) waitpid(childPid, &status, 0);
+ }
+ return;
+}
+
+/*
+ * 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(pSrcFile, pDstFile, numBytes)
+ FILE *pSrcFile,
+ *pDstFile;
+ int numBytes;
+{
+ char buf[10240];
+ int bytesWritten = 0, bytesToXfer;
+
+ for(bytesToXfer = min(sizeof(buf)*sizeof(char), numBytes);
+ bytesToXfer > 0;
+ bytesToXfer = min(sizeof(buf)*sizeof(char), 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(ppSrcFile, pSrcFileName, pDstFile)
+ FILE **ppSrcFile,
+ *pDstFile;
+ char **pSrcFileName;
+{
+ 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, 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), (size_t) 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;
+}
+
+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;
+}
+
+Bool
+XpOpenTmpFile(
+ char *mode,
+ char **fname,
+ FILE **stream)
+{
+ 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);
+ return TRUE;
+}