blob: 20c5dcfb9c2b7f9e136af050b0d1b4df6764df96 [file] [log] [blame]
/*
* 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 */
/*
* 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);
}
}
/*
* Copy the print file to stdout...
*/
while (copies > 0)
{
copies --;
/*
* Read the first line...
*/
linelen = sizeof(line);
if (!psgets(line, &linelen, fp))
break;
/*
* Handle leading PJL fun...
*/
if (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
{
/*
* Yup, we have leading PJL fun, so copy it until we hit a line
* with "ENTER LANGUAGE"...
*/
while (strstr(line, "ENTER LANGUAGE") == NULL)
{
fwrite(line, 1, linelen, stdout);
linelen = sizeof(line);
if (psgets(line, &linelen, fp) == NULL)
break;
}
}
else
{
/*
* No PJL stuff, just add the UEL...
*/
fputs("\033%-12345X", stdout);
}
/*
* Switch to TBCP mode...
*/
fputs("\001M", stdout);
/*
* Loop until we see end-of-file...
*/
while (pswrite(line, linelen) > 0)
{
linelen = sizeof(line);
if (psgets(line, &linelen, fp) == NULL)
break;
}
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 0x1b : /* CTRL-[ (aka ESC) */
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);
}