#include <cups/cups.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h>
#if defined(WIN32) || defined(__EMX__)
# include <io.h>
#else
# include <unistd.h>
# include <fcntl.h>
# include <termios.h>
#endif
#if defined(WIN32) || defined(__EMX__)
# include <winsock.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
#endif
#ifdef __sgi
# include <invent.h>
# ifndef INV_EPP_ECP_PLP
# define INV_EPP_ECP_PLP 6
# define INV_ASO_SERIAL 14
# define INV_IOC3_DMA 16
# define INV_IOC3_PIO 17
# define INV_ISA_DMA 19
# endif
#endif
void list_devices(void);
int
main(int argc,
char *argv[])
{
char method[1024],
hostname[1024],
username[1024],
resource[1024],
*options;
int port;
int copies;
int fd_out,
fd_in,
error,
backchannel;
struct sockaddr_in addr;
struct hostent *hostaddr;
int wbytes;
int nbytes,
tbytes;
char buffer[8192],
*bufptr;
struct timeval timeout;
fd_set input;
struct termios opts;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
if (argc == 1)
{
list_devices();
return (0);
}
else if (argc < 6 || argc > 7)
{
fputs("Usage: canon job-id user title copies options [file]\n", stderr);
return (1);
}
if (argc == 6)
{
fd_in = fileno(stdin);
copies = 1;
}
else
{
if ((fd_in = open(argv[6], O_RDONLY)) < 0)
{
perror("ERROR: unable to open print file");
return (1);
}
copies = atoi(argv[4]);
}
httpSeparate(argv[0], method, username, hostname, &port, resource);
if ((options = strchr(resource, '?')) != NULL)
{
*options++ = '\0';
}
if (hostname[0])
{
if ((hostaddr = gethostbyname(hostname)) == NULL)
{
fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s",
hostname, strerror(errno));
return (1);
}
if (port == 0)
port = 9100;
fprintf(stderr, "INFO: Attempting to connect to printer %s on port %d\n",
hostname, port);
memset(&addr, 0, sizeof(addr));
memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length);
addr.sin_family = hostaddr->h_addrtype;
addr.sin_port = htons(port);
for (;;)
{
if ((fd_out = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("ERROR: Unable to create socket");
return (1);
}
if (connect(fd_out, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
error = errno;
close(fd_out);
fd_out = -1;
if (error == ECONNREFUSED)
{
fprintf(stderr, "INFO: Network printer \'%s\' is busy; will retry in 30 seconds...\n",
hostname);
sleep(30);
}
else
{
perror("ERROR: Unable to connect to printer");
sleep(30);
}
}
else
break;
}
fputs("INFO: Connected to printer, sending print job...\n", stderr);
}
else
{
do
{
if ((fd_out = open(resource, O_RDWR | O_EXCL)) == -1)
{
if (errno == EBUSY)
{
fputs("INFO: Parallel port busy; will retry in 30 seconds...\n", stderr);
sleep(30);
}
else
{
perror("ERROR: Unable to open parallel port device file");
return (1);
}
}
}
while (fd_out < 0);
tcgetattr(fd_out, &opts);
opts.c_cflag |= CREAD;
opts.c_lflag &= ~(ICANON | ECHO | ISIG);
tcsetattr(fd_out, TCSANOW, &opts);
}
#ifdef HAVE_SIGSET
sigset(SIGTERM, SIG_IGN);
#elif defined(HAVE_SIGACTION)
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_handler = SIG_IGN;
sigaction(SIGTERM, &action, NULL);
#else
signal(SIGTERM, SIG_IGN);
#endif
backchannel = 1;
while (copies > 0)
{
copies --;
if (fd_in != fileno(stdin))
{
fputs("PAGE: 1 1\n", stderr);
lseek(fd_in, 0, SEEK_SET);
}
tbytes = 0;
while ((nbytes = read(fd_in, buffer, sizeof(buffer))) > 0)
{
tbytes += nbytes;
bufptr = buffer;
while (nbytes > 0)
{
if ((wbytes = write(fd_out, bufptr, nbytes)) < 0)
{
perror("ERROR: Unable to send print file to printer");
break;
}
nbytes -= wbytes;
bufptr += wbytes;
}
if (nbytes > 0)
break;
if (!backchannel)
continue;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&input);
FD_SET(fd_out, &input);
if (select(fd_out + 1, &input, NULL, NULL, &timeout) > 0)
{
if ((nbytes = read(fd_out, buffer, sizeof(buffer) - 1)) < 0)
{
fprintf(stderr, "ERROR: Back-channel read error - %s!\n",
strerror(errno));
backchannel = 0;
continue;
}
if (nbytes == 0)
continue;
buffer[nbytes] = '\0';
if (strncmp(buffer, "@BDC ", 5) != 0)
fprintf(stderr, "WARNING: Received %d bytes of unknown back-channel data!\n",
nbytes);
else
{
for (bufptr = buffer; *bufptr && *bufptr != '\n'; bufptr ++);
if (*bufptr == '\n')
bufptr ++;
strcpy(buffer, bufptr);
for (bufptr = buffer; *bufptr && *bufptr != ';'; bufptr ++);
*bufptr = '\0';
if (strncmp(buffer, "IQ:", 3) == 0)
{
int i;
int levels[6];
buffer[12] = '\0';
for (i = 0, bufptr = buffer; i < 6; i ++, bufptr += 2)
{
if (isalpha(bufptr[0]))
levels[i] = (tolower(bufptr[0]) - 'a' + 10) << 16;
else
levels[i] = (bufptr[0] - '0') << 16;
if (isalpha(bufptr[1]))
levels[i] |= tolower(bufptr[1]) - 'a' + 10;
else
levels[i] |= bufptr[1] - '0';
}
switch (i)
{
case 1 :
case 2 :
fprintf(stderr, "K=%d\n", levels[0]);
break;
case 3 :
fprintf(stderr, "C=%d M=%d Y=%d\n", levels[0], levels[1],
levels[2]);
break;
case 4 :
case 5 :
fprintf(stderr, "K=%d C=%d M=%d Y=%d\n", levels[0],
levels[1], levels[2], levels[3]);
break;
case 6 :
fprintf(stderr, "K=%d C=%d M=%d Y=%d LC=%d LM=%d\n",
levels[0], levels[1], levels[2], levels[3],
levels[4], levels[5]);
break;
}
}
else
fprintf(stderr, "INFO: %s\n", buffer);
}
}
else if (argc > 6)
fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes);
}
}
close(fd_out);
if (fd_in != fileno(stdin))
close(fd_in);
return (0);
}
void
list_devices(void)
{
#ifdef __linux
int i;
int fd;
char device[255];
FILE *probe;
char line[1024],
*delim,
make[IPP_MAX_NAME],
model[IPP_MAX_NAME];
for (i = 0; i < 4; i ++)
{
sprintf(device, "/proc/parport/%d/autoprobe", i);
if ((probe = fopen(device, "r")) != NULL)
{
memset(make, 0, sizeof(make));
memset(model, 0, sizeof(model));
strcpy(model, "CANON");
while (fgets(line, sizeof(line), probe) != NULL)
{
if ((delim = strrchr(line, ';')) != NULL)
*delim = '\0';
else if ((delim = strrchr(line, '\n')) != NULL)
*delim = '\0';
if (strncmp(line, "MODEL:", 6) == 0 &&
strncmp(line, "MODEL:CANON", 13) != 0)
strncpy(model, line + 6, sizeof(model) - 1);
else if (strncmp(line, "MANUFACTURER:", 13) == 0 &&
strncmp(line, "MANUFACTURER:CANON", 20) != 0)
strncpy(make, line + 13, sizeof(make) - 1);
}
fclose(probe);
if (strcmp(make, "CANON") == 0)
printf("direct canon:/dev/lp%d \"%s %s\" \"Parallel Port #%d\"\n",
i, make, model, i + 1);
}
else
{
sprintf(device, "/dev/lp%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"Parallel Port #%d\"\n", device, i + 1);
}
}
}
if ((probe = fopen("/proc/bus/usb/devices", "r")) != NULL)
{
i = 0;
memset(make, 0, sizeof(make));
memset(model, 0, sizeof(model));
while (fgets(line, sizeof(line), probe) != NULL)
{
if ((delim = strrchr(line, '\n')) != NULL)
*delim = '\0';
if (strncmp(line, "S:", 2) == 0)
{
if (strncmp(line, "S: Manufacturer=", 17) == 0)
{
strncpy(make, line + 17, sizeof(make) - 1);
if (strcmp(make, "Hewlett-Packard") == 0)
strcpy(make, "HP");
}
else if (strncmp(line, "S: Product=", 12) == 0)
strncpy(model, line + 12, sizeof(model) - 1);
}
else if (strncmp(line, "I:", 2) == 0 &&
strstr(line, "Driver=printer") != NULL &&
make[0] && model[0])
{
if (strcmp(make, "CANON") == 0)
{
sprintf(device, "/dev/usb/lp%d", i);
if (access(device, 0))
{
sprintf(device, "/dev/usb/usblp%d", i);
if (access(device, 0))
sprintf(device, "/dev/usblp%d", i);
}
printf("direct canon:%s \"%s %s\" \"USB Printer #%d\"\n",
device, make, model, i + 1);
}
i ++;
memset(make, 0, sizeof(make));
memset(model, 0, sizeof(model));
}
}
fclose(probe);
}
else
{
for (i = 0; i < 8; i ++)
{
sprintf(device, "/dev/usb/lp%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"USB Printer #%d\"\n", device, i + 1);
}
sprintf(device, "/dev/usb/usblp%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"USB Printer #%d\"\n", device, i + 1);
}
sprintf(device, "/dev/usblp%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"USB Printer #%d\"\n", device, i + 1);
}
}
}
#elif defined(__sgi)
int i, j, n;
char device[255];
inventory_t *inv;
setinvent();
while ((inv = getinvent()) != NULL)
{
if (inv->inv_class == INV_PARALLEL && inv->inv_type == INV_EPP_ECP_PLP)
{
puts("direct canon:/dev/plpbi \"CANON\" \"Onboard Parallel Port\"");
}
}
endinvent();
#elif defined(__sun)
int i, j, n;
char device[255];
for (i = 0; i < 10; i ++)
{
sprintf(device, "/dev/ecpp%d", i);
if (access(device, 0) == 0)
printf("direct canon:%s \"CANON\" \"Sun IEEE-1284 Parallel Port #%d\"\n",
device, i + 1);
}
for (i = 0; i < 3; i ++)
{
sprintf(device, "/dev/lp%d", i);
if (access(device, 0) == 0)
printf("direct canon:%s \"CANON\" \"PC Parallel Port #%d\"\n",
device, i + 1);
}
#elif defined(FreeBSD) || defined(OpenBSD) || defined(NetBSD)
int i;
int fd;
char device[255];
for (i = 0; i < 3; i ++)
{
sprintf(device, "/dev/lpt%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"Parallel Port #%d (interrupt-driven)\"\n", device, i + 1);
}
sprintf(device, "/dev/lpa%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"Parallel Port #%d (polled)\"\n", device, i + 1);
}
}
for (i = 0; i < 3; i ++)
{
sprintf(device, "/dev/ulpt%d", i);
if ((fd = open(device, O_RDWR)) >= 0)
{
close(fd);
printf("direct canon:%s \"CANON\" \"USB Port #%d\"\n", device, i + 1);
}
}
#endif
}