#ifdef __linux
# include <sys/ioctl.h>
# include <linux/lp.h>
# define IOCNR_GET_DEVICE_ID 1
# define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
#endif
#ifdef __sun
# ifdef __sparc
# include <sys/ecppio.h>
# else
# include <sys/ioccom.h>
# include <sys/ecppsys.h>
# endif
#endif
void decode_device_id(int port, const char *device_id,
char *make_model, int mmsize,
char *uri, int urisize);
int open_device(const char *uri);
int
print_device(const char *uri,
const char *hostname,
const char *resource,
const char *options,
int fp,
int copies)
{
int fd;
int wbytes;
size_t nbytes,
tbytes;
char buffer[8192],
*bufptr;
struct termios opts;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
#ifdef __linux
unsigned int status;
#endif
do
{
if ((fd = open_device(uri)) == -1)
{
if (errno == EBUSY)
{
fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr);
sleep(30);
}
else if (errno == ENXIO || errno == EIO || errno == ENOENT)
{
fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr);
sleep(30);
}
else
{
fprintf(stderr, "ERROR: Unable to open USB device \"%s\": %s\n",
uri, strerror(errno));
return (1);
}
}
}
while (fd < 0);
tcgetattr(fd, &opts);
opts.c_lflag &= ~(ICANON | ECHO | ISIG);
tcsetattr(fd, TCSANOW, &opts);
if (fp)
{
#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
}
#if defined(__linux) && defined(LP_POUTPA)
if (ioctl(fd, LPGETSTATUS, &status) == 0)
{
fprintf(stderr, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status);
if (status & LP_POUTPA)
fputs("WARNING: Media tray empty!\n", stderr);
else if (!(status & LP_PERRORP))
fputs("WARNING: Printer fault!\n", stderr);
else if (!(status & LP_PSELECD))
fputs("WARNING: Printer off-line.\n", stderr);
}
#endif
wbytes = 0;
while (copies > 0)
{
copies --;
if (fp != 0)
{
fputs("PAGE: 1 1\n", stderr);
lseek(fp, 0, SEEK_SET);
}
tbytes = 0;
while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0)
{
tbytes += nbytes;
bufptr = buffer;
while (nbytes > 0)
{
if ((wbytes = write(fd, bufptr, nbytes)) < 0)
if (errno == ENOTTY)
wbytes = write(fd, bufptr, nbytes);
if (wbytes < 0)
{
perror("ERROR: Unable to send print file to printer");
break;
}
nbytes -= wbytes;
bufptr += wbytes;
}
if (wbytes < 0)
break;
if (fp)
fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
(unsigned long)tbytes);
}
}
close(fd);
return (wbytes < 0);
}
void
decode_device_id(int port,
const char *device_id,
char *make_model,
int mmsize,
char *uri,
int urisize)
{
char *attr,
*delim,
*uriptr,
*mfg,
*mdl,
serial_number[1024];
if ((attr = strstr(device_id, "DES:")) != NULL)
attr += 4;
else if ((attr = strstr(device_id, "DESCRIPTION:")) != NULL)
attr += 12;
if ((mfg = strstr(device_id, "MANUFACTURER:")) != NULL)
mfg += 13;
else if ((mfg = strstr(device_id, "MFG:")) != NULL)
mfg += 4;
if ((mdl = strstr(device_id, "MODEL:")) != NULL)
mdl += 6;
else if ((mdl = strstr(device_id, "MDL:")) != NULL)
mdl += 4;
if (attr)
{
if (strncasecmp(attr, "Hewlett-Packard ", 16) == 0)
{
strlcpy(make_model, "HP ", mmsize);
strlcpy(make_model + 3, attr + 16, mmsize - 3);
}
else
{
strlcpy(make_model, attr, mmsize);
}
if ((delim = strchr(make_model, ';')) != NULL)
*delim = '\0';
}
else if (mfg && mdl)
{
strlcpy(make_model, mfg, mmsize);
if ((delim = strchr(make_model, ';')) != NULL)
*delim = '\0';
strlcat(make_model, " ", mmsize);
strlcat(make_model, mdl, mmsize);
if ((delim = strchr(make_model, ';')) != NULL)
*delim = '\0';
}
else
{
strlcpy(make_model, "Unknown", mmsize);
}
if ((attr = strstr(device_id, "SERN:")) != NULL)
attr += 5;
else if ((attr = strstr(device_id, "SERIALNUMBER:")) != NULL)
attr += 13;
else if ((attr = strstr(device_id, ";SN:")) != NULL)
attr += 4;
if (mfg)
{
if ((delim = strchr(mfg, ';')) != NULL)
*delim = '\0';
}
if (mdl)
{
if ((delim = strchr(mdl, ';')) != NULL)
*delim = '\0';
}
if (attr)
{
strlcpy(serial_number, attr, sizeof(serial_number));
if ((delim = strchr(serial_number, ';')) != NULL)
*delim = '\0';
}
else
serial_number[0] = '\0';
strlcpy(uri, "usb://", urisize);
for (uriptr = uri + 6, delim = make_model;
*delim && uriptr < (uri + urisize - 1);
delim ++)
if (*delim == ' ')
{
delim ++;
*uriptr++ = '/';
break;
}
else
*uriptr++ = *delim;
for (; *delim && uriptr < (uri + urisize - 3); delim ++)
if (*delim == ' ')
{
*uriptr++ = '%';
*uriptr++ = '2';
*uriptr++ = '0';
}
else
*uriptr++ = *delim;
*uriptr = '\0';
if (serial_number[0])
{
strlcat(uri, "?serial=", urisize);
strlcat(uri, serial_number, urisize);
}
}
void
list_devices(void)
{
#ifdef __linux
int i;
int length;
int fd;
char format[255],
device[255],
device_id[1024],
device_uri[1024],
make_model[1024];
if (access("/dev/usblp0", 0) == 0)
strcpy(format, "/dev/usblp%d");
else if (access("/dev/usb/usblp0", 0) == 0)
strcpy(format, "/dev/usb/usblp%d");
else
strcpy(format, "/dev/usb/lp%d");
for (i = 0; i < 16; i ++)
{
sprintf(device, format, i);
if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
{
if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0)
{
length = (((unsigned)device_id[0] & 255) << 8) +
((unsigned)device_id[1] & 255);
if (length > (sizeof(device_id) - 2))
length = (((unsigned)device_id[1] & 255) << 8) +
((unsigned)device_id[0] & 255);
if (length > (sizeof(device_id) - 2))
length = sizeof(device_id) - 2;
memmove(device_id, device_id + 2, length);
device_id[length] = '\0';
}
else
device_id[0] = '\0';
close(fd);
}
else
device_id[0] = '\0';
if (device_id[0])
{
decode_device_id(i, device_id, make_model, sizeof(make_model),
device_uri, sizeof(device_uri));
printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri,
make_model, i + 1);
}
else
printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
}
#elif defined(__sgi)
#elif defined(__sun)
int i;
int fd;
char device[255],
device_id[1024],
device_uri[1024],
make_model[1024];
# ifdef ECPPIOC_GETDEVID
struct ecpp_device_id did;
# endif
for (i = 0; i < 8; i ++)
{
sprintf(device, "/dev/usb/printer%d", i);
# ifndef ECPPIOC_GETDEVID
if (!access(device, 0))
printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
# else
if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
{
did.mode = ECPP_CENTRONICS;
did.len = sizeof(device_id);
did.rlen = 0;
did.addr = device_id;
if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0)
{
if (did.rlen < (sizeof(device_id) - 1))
device_id[did.rlen] = '\0';
else
device_id[sizeof(device_id) - 1] = '\0';
}
else
device_id[0] = '\0';
close(fd);
}
else
device_id[0] = '\0';
if (device_id[0])
{
decode_device_id(i, device_id, make_model, sizeof(make_model),
device_uri, sizeof(device_uri));
printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri,
make_model, i + 1);
}
else
printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
# endif
}
#elif defined(__hpux)
#elif defined(__osf)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
int i;
char device[255];
for (i = 0; i < 8; i ++)
{
sprintf(device, "/dev/ulpt%d", i);
if (!access(device, 0))
printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
sprintf(device, "/dev/unlpt%d", i);
if (!access(device, 0))
printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1);
}
#endif
}
int
open_device(const char *uri)
{
if (strncmp(uri, "usb:/dev/", 9) == 0)
return (open(uri + 4, O_RDWR | O_EXCL));
#ifdef __linux
else if (strncmp(uri, "usb://", 6) == 0)
{
int i;
int busy;
int length;
int fd;
char format[255],
device[255],
device_id[1024],
make_model[1024],
device_uri[1024];
if (access("/dev/usblp0", 0) == 0)
strcpy(format, "/dev/usblp%d");
else if (access("/dev/usb/usblp0", 0) == 0)
strcpy(format, "/dev/usb/usblp%d");
else
strcpy(format, "/dev/usb/lp%d");
do
{
for (busy = 0, i = 0; i < 16; i ++)
{
sprintf(device, format, i);
if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
{
if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0)
{
length = (((unsigned)device_id[0] & 255) << 8) +
((unsigned)device_id[1] & 255);
memmove(device_id, device_id + 2, length);
device_id[length] = '\0';
}
else
device_id[0] = '\0';
}
else
{
if (errno == EBUSY)
busy = 1;
device_id[0] = '\0';
}
if (device_id[0])
{
decode_device_id(i, device_id, make_model, sizeof(make_model),
device_uri, sizeof(device_uri));
if (strcmp(uri, device_uri) == 0)
{
fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device);
return (fd);
}
}
if (fd >= 0)
close(fd);
}
if (busy)
{
fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
stderr);
sleep(5);
}
}
while (busy);
errno = ENODEV;
return (-1);
}
#elif defined(__sun) && defined(ECPPIOC_GETDEVID)
else if (strncmp(uri, "usb://", 6) == 0)
{
int i;
int busy;
int fd;
char device[255],
device_id[1024],
make_model[1024],
device_uri[1024];
struct ecpp_device_id did;
do
{
for (i = 0, busy = 0; i < 8; i ++)
{
sprintf(device, "/dev/usb/printer%d", i);
if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
{
did.mode = ECPP_CENTRONICS;
did.len = sizeof(device_id);
did.rlen = 0;
did.addr = device_id;
if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0)
{
if (did.rlen < (sizeof(device_id) - 1))
device_id[did.rlen] = '\0';
else
device_id[sizeof(device_id) - 1] = '\0';
}
else
device_id[0] = '\0';
}
else
{
if (errno == EBUSY)
busy = 1;
device_id[0] = '\0';
}
if (device_id[0])
{
decode_device_id(i, device_id, make_model, sizeof(make_model),
device_uri, sizeof(device_uri));
if (strcmp(uri, device_uri) == 0)
return (fd);
}
if (fd >= 0)
close(fd);
}
if (busy)
{
fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
stderr);
sleep(5);
}
}
while (busy);
errno = ENODEV;
return (-1);
}
#endif
else
{
errno = ENODEV;
return (-1);
}
}