mirror of https://gitee.com/openkylin/cups.git
273 lines
5.1 KiB
C
273 lines
5.1 KiB
C
/*
|
|
* TBCP port monitor for CUPS.
|
|
*
|
|
* Copyright 2007-2014 by Apple Inc.
|
|
* Copyright 1993-2006 by Easy Software Products.
|
|
*
|
|
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
|
|
*/
|
|
|
|
/*
|
|
* Include necessary headers...
|
|
*/
|
|
|
|
#include <cups/cups-private.h>
|
|
#include <cups/ppd.h>
|
|
|
|
|
|
/*
|
|
* Local functions...
|
|
*/
|
|
|
|
static char *psgets(char *buf, size_t *bytes, FILE *fp);
|
|
static ssize_t pswrite(const char *buf, size_t bytes);
|
|
|
|
|
|
/*
|
|
* 'main()' - Main entry...
|
|
*/
|
|
|
|
int /* O - Exit status */
|
|
main(int argc, /* I - Number of command-line args */
|
|
char *argv[]) /* I - Command-line arguments */
|
|
{
|
|
FILE *fp; /* File to print */
|
|
int copies; /* Number of copies left */
|
|
char line[1024]; /* Line/buffer from stream/file */
|
|
size_t linelen; /* Length of line */
|
|
ppd_file_t *ppd; /* PPD file */
|
|
|
|
|
|
/*
|
|
* Check command-line...
|
|
*/
|
|
|
|
if (argc != 6 && argc != 7)
|
|
{
|
|
_cupsLangPrintf(stderr,
|
|
_("Usage: %s job-id user title copies options [file]"),
|
|
argv[0]);
|
|
return (1);
|
|
}
|
|
|
|
if (argc == 6)
|
|
{
|
|
copies = 1;
|
|
fp = stdin;
|
|
}
|
|
else
|
|
{
|
|
copies = atoi(argv[4]);
|
|
fp = fopen(argv[6], "rb");
|
|
|
|
if (!fp)
|
|
{
|
|
perror(argv[6]);
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Open the PPD file as needed...
|
|
*/
|
|
|
|
ppd = ppdOpenFile(getenv("PPD"));
|
|
|
|
/*
|
|
* Copy the print file to stdout...
|
|
*/
|
|
|
|
while (copies > 0)
|
|
{
|
|
copies --;
|
|
|
|
if (ppd && ppd->jcl_begin)
|
|
fputs(ppd->jcl_begin, stdout);
|
|
if (ppd && ppd->jcl_ps)
|
|
fputs(ppd->jcl_ps, stdout);
|
|
|
|
if (!ppd || ppd->language_level == 1)
|
|
{
|
|
/*
|
|
* Use setsoftwareiomode for BCP mode...
|
|
*/
|
|
|
|
puts("%!PS-Adobe-3.0 ExitServer");
|
|
puts("%%Title: (BCP - Level 1)");
|
|
puts("%%EndComments");
|
|
puts("%%BeginExitServer: 0");
|
|
puts("serverdict begin 0 exitserver");
|
|
puts("%%EndExitServer");
|
|
puts("statusdict begin");
|
|
puts("/setsoftwareiomode known {100 setsoftwareiomode}");
|
|
puts("end");
|
|
puts("%EOF");
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Use setdevparams for BCP mode...
|
|
*/
|
|
|
|
puts("%!PS-Adobe-3.0");
|
|
puts("%%Title: (BCP - Level 2)");
|
|
puts("%%EndComments");
|
|
puts("currentsysparams");
|
|
puts("/CurInputDevice 2 copy known {");
|
|
puts("get");
|
|
puts("<</Protocol /Binary>> setdevparams");
|
|
puts("}{");
|
|
puts("pop pop");
|
|
puts("} ifelse");
|
|
puts("%EOF");
|
|
}
|
|
|
|
if (ppd && ppd->jcl_end)
|
|
fputs(ppd->jcl_end, stdout);
|
|
else if (!ppd || ppd->num_filters == 0)
|
|
putchar(0x04);
|
|
|
|
/*
|
|
* Loop until we see end-of-file...
|
|
*/
|
|
|
|
do
|
|
{
|
|
linelen = sizeof(line);
|
|
if (psgets(line, &linelen, fp) == NULL)
|
|
break;
|
|
}
|
|
while (pswrite(line, linelen) > 0);
|
|
|
|
fflush(stdout);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
/*
|
|
* 'psgets()' - Get a line from a file.
|
|
*
|
|
* Note:
|
|
*
|
|
* This function differs from the gets() function in that it
|
|
* handles any combination of CR, LF, or CR LF to end input
|
|
* lines.
|
|
*/
|
|
|
|
static char * /* O - String or NULL if EOF */
|
|
psgets(char *buf, /* I - Buffer to read into */
|
|
size_t *bytes, /* IO - Length of buffer */
|
|
FILE *fp) /* I - File to read from */
|
|
{
|
|
char *bufptr; /* Pointer into buffer */
|
|
int ch; /* Character from file */
|
|
size_t len; /* Max length of string */
|
|
|
|
|
|
len = *bytes - 1;
|
|
bufptr = buf;
|
|
ch = EOF;
|
|
|
|
while ((size_t)(bufptr - buf) < len)
|
|
{
|
|
if ((ch = getc(fp)) == EOF)
|
|
break;
|
|
|
|
if (ch == '\r')
|
|
{
|
|
/*
|
|
* Got a CR; see if there is a LF as well...
|
|
*/
|
|
|
|
ch = getc(fp);
|
|
|
|
if (ch != EOF && ch != '\n')
|
|
{
|
|
ungetc(ch, fp); /* Nope, save it for later... */
|
|
ch = '\r';
|
|
}
|
|
else
|
|
*bufptr++ = '\r';
|
|
break;
|
|
}
|
|
else if (ch == '\n')
|
|
break;
|
|
else
|
|
*bufptr++ = (char)ch;
|
|
}
|
|
|
|
/*
|
|
* Add a trailing newline if it is there...
|
|
*/
|
|
|
|
if (ch == '\n' || ch == '\r')
|
|
{
|
|
if ((size_t)(bufptr - buf) < len)
|
|
*bufptr++ = (char)ch;
|
|
else
|
|
ungetc(ch, fp);
|
|
}
|
|
|
|
/*
|
|
* Nul-terminate the string and return it (or NULL for EOF).
|
|
*/
|
|
|
|
*bufptr = '\0';
|
|
*bytes = (size_t)(bufptr - buf);
|
|
|
|
if (ch == EOF && bufptr == buf)
|
|
return (NULL);
|
|
else
|
|
return (buf);
|
|
}
|
|
|
|
|
|
/*
|
|
* 'pswrite()' - Write data from a file.
|
|
*/
|
|
|
|
static ssize_t /* O - Number of bytes written */
|
|
pswrite(const char *buf, /* I - Buffer to write */
|
|
size_t bytes) /* I - Bytes to write */
|
|
{
|
|
size_t count; /* Remaining bytes */
|
|
|
|
|
|
for (count = bytes; count > 0; count --, buf ++)
|
|
switch (*buf)
|
|
{
|
|
case 0x04 : /* CTRL-D */
|
|
if (bytes == 1)
|
|
{
|
|
/*
|
|
* Don't quote the last CTRL-D...
|
|
*/
|
|
|
|
putchar(0x04);
|
|
break;
|
|
}
|
|
|
|
case 0x01 : /* CTRL-A */
|
|
case 0x03 : /* CTRL-C */
|
|
case 0x05 : /* CTRL-E */
|
|
case 0x11 : /* CTRL-Q */
|
|
case 0x13 : /* CTRL-S */
|
|
case 0x14 : /* CTRL-T */
|
|
case 0x1c : /* CTRL-\ */
|
|
if (putchar(0x01) < 0)
|
|
return (-1);
|
|
if (putchar(*buf ^ 0x40) < 0)
|
|
return (-1);
|
|
break;
|
|
|
|
default :
|
|
if (putchar(*buf) < 0)
|
|
return (-1);
|
|
break;
|
|
}
|
|
|
|
return ((ssize_t)bytes);
|
|
}
|