2006-12-06 17:25:32 -06:00
|
|
|
/****************************************************************************\
|
|
|
|
* Copyright (C) 1992 by Michael K. Johnson, johnsonm@nigel.vnet.net *
|
|
|
|
* *
|
|
|
|
* This file is placed under the conditions of the GNU public *
|
|
|
|
* license, version 2, or any later version. See file COPYING *
|
|
|
|
* for information on distribution conditions. *
|
|
|
|
\****************************************************************************/
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
/* $Id: tunelp.c,v 1.6 1995/06/04 01:47:11 faith Exp $
|
|
|
|
* $Log: tunelp.c,v $
|
|
|
|
* Revision 1.6 1995/06/04 01:47:11 faith
|
|
|
|
* Changes for util-linux-2.4
|
|
|
|
*
|
|
|
|
* Revision 1.5 1995/03/12 01:29:50 faith
|
|
|
|
* util-linux-2.1
|
2006-12-06 17:25:32 -06:00
|
|
|
*
|
|
|
|
* Revision 1.5 1995/01/13 10:33:43 johnsonm
|
|
|
|
* Chris's changes for new ioctl numbers and backwards compatibility
|
|
|
|
* and the reset ioctl.
|
|
|
|
*
|
|
|
|
* Revision 1.4 1995/01/03 17:42:14 johnsonm
|
|
|
|
* -s isn't supposed to take an argument; removed : after s in getopt...
|
|
|
|
*
|
|
|
|
* Revision 1.3 1995/01/03 07:36:49 johnsonm
|
|
|
|
* Fixed typo
|
|
|
|
*
|
|
|
|
* Revision 1.2 1995/01/03 07:33:44 johnsonm
|
|
|
|
* revisions for lp driver updates in Linux 1.1.76
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include<unistd.h>
|
|
|
|
#include<stdio.h>
|
|
|
|
#include<fcntl.h>
|
|
|
|
#include<linux/lp.h>
|
|
|
|
#include<linux/fs.h>
|
|
|
|
#include<sys/ioctl.h>
|
|
|
|
#include<sys/stat.h>
|
|
|
|
#include<sys/types.h>
|
|
|
|
#include<malloc.h>
|
|
|
|
#include<string.h>
|
|
|
|
#include<errno.h>
|
|
|
|
|
|
|
|
struct command {
|
|
|
|
long op;
|
|
|
|
long val;
|
|
|
|
struct command *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void print_usage(char *progname) {
|
|
|
|
printf("Usage: %s <device> [ -i <IRQ> | -t <TIME> | -c <CHARS> | -w <WAIT> | \n"
|
|
|
|
" -a [on|off] | -o [on|off] | -C [on|off] | -q [on|off] | -s ]\n", progname);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void *mylloc(long size) {
|
|
|
|
void *ptr;
|
|
|
|
if(!(ptr = (void*)malloc(size))) {
|
|
|
|
perror("malloc error");
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long get_val(char *val) {
|
|
|
|
long ret;
|
|
|
|
if (!(sscanf(val, "%d", &ret) == 1)) {
|
|
|
|
perror("sscanf error");
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
long get_onoff(char *val) {
|
|
|
|
if (!strncasecmp("on", val, 2))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main (int argc, char ** argv) {
|
|
|
|
int c, fd, irq, status, show_irq, offset = 0, retval;
|
|
|
|
char *progname;
|
|
|
|
char *filename;
|
|
|
|
struct stat statbuf;
|
|
|
|
struct command *cmds, *cmdst;
|
|
|
|
|
|
|
|
|
|
|
|
progname = argv[0];
|
|
|
|
if (argc < 2) print_usage(progname);
|
|
|
|
|
|
|
|
filename = strdup(argv[1]);
|
|
|
|
fd = open(filename, O_WRONLY|O_NONBLOCK, 0);
|
|
|
|
/* Need to open O_NONBLOCK in case ABORTOPEN is already set and
|
|
|
|
printer is off or off-line or in an error condition. Otherwise
|
|
|
|
we would abort... */
|
|
|
|
if (fd < 0) {
|
|
|
|
perror(argv[1]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fstat(fd, &statbuf);
|
|
|
|
|
|
|
|
if((!S_ISCHR(statbuf.st_mode)) || (MAJOR(statbuf.st_rdev) != 6 )
|
|
|
|
|| (MINOR(statbuf.st_rdev) > 3)) {
|
|
|
|
printf("%s: %s not an lp device.\n", argv[0], argv[1]);
|
|
|
|
print_usage(progname);
|
|
|
|
}
|
|
|
|
|
|
|
|
cmdst = cmds = mylloc(sizeof(struct command));
|
|
|
|
cmds->next = 0;
|
|
|
|
|
|
|
|
show_irq = 1;
|
|
|
|
while ((c = getopt(argc, argv, "t:c:w:a:i:ho:C:sq:r")) != EOF) {
|
|
|
|
switch (c) {
|
|
|
|
case 'h':
|
|
|
|
print_usage(progname);
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
cmds->op = LPSETIRQ;
|
|
|
|
cmds->val = get_val(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
cmds->op = LPTIME;
|
|
|
|
cmds->val = get_val(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
cmds->op = LPCHAR;
|
|
|
|
cmds->val = get_val(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
cmds->op = LPWAIT;
|
|
|
|
cmds->val = get_val(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
cmds->op = LPABORT;
|
|
|
|
cmds->val = get_onoff(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
if (get_onoff(optarg)) {
|
|
|
|
show_irq=1;
|
|
|
|
} else {
|
|
|
|
show_irq=0;
|
|
|
|
}
|
|
|
|
#ifdef LPGETSTATUS
|
|
|
|
case 'o':
|
|
|
|
cmds->op = LPABORTOPEN;
|
|
|
|
cmds->val = get_onoff(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
cmds->op = LPCAREFUL;
|
|
|
|
cmds->val = get_onoff(optarg);
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
show_irq = 0;
|
|
|
|
cmds->op = LPGETSTATUS;
|
|
|
|
cmds->val = 0;
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef LPRESET
|
|
|
|
case 'r':
|
|
|
|
cmds->op = LPRESET;
|
|
|
|
cmds->val = 0;
|
|
|
|
cmds->next = mylloc(sizeof(struct command));
|
|
|
|
cmds = cmds->next; cmds->next = 0;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default: print_usage(progname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow for binaries compiled under a new kernel to work on the old ones */
|
2006-12-06 17:25:33 -06:00
|
|
|
if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0 && errno == EINVAL)
|
2006-12-06 17:25:32 -06:00
|
|
|
offset = 0x0600; /* We don't understand the new ioctls */
|
|
|
|
|
|
|
|
cmds = cmdst;
|
|
|
|
while (cmds->next) {
|
|
|
|
#ifdef LPGETSTATUS
|
|
|
|
if (cmds->op == LPGETSTATUS) {
|
|
|
|
status = 0xdeadbeef;
|
|
|
|
retval = ioctl(fd, LPGETSTATUS - offset, &status);
|
|
|
|
if (retval < 0)
|
|
|
|
perror("LPGETSTATUS error");
|
|
|
|
else {
|
|
|
|
if (status == 0xdeadbeef) /* a few 1.1.7x kernels will do this */
|
|
|
|
status = retval;
|
|
|
|
printf("%s status is %d", filename, status);
|
|
|
|
if (!(status & LP_PBUSY)) printf(", busy");
|
|
|
|
if (!(status & LP_PACK)) printf(", ready");
|
|
|
|
if ((status & LP_POUTPA)) printf(", out of paper");
|
|
|
|
if ((status & LP_PSELECD)) printf(", on-line");
|
|
|
|
if (!(status & LP_PERRORP)) printf(", error");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
#endif /* LPGETSTATUS */
|
|
|
|
if (ioctl(fd, cmds->op - offset, cmds->val) < 0) {
|
|
|
|
perror("tunelp: ioctl");
|
|
|
|
}
|
|
|
|
cmdst = cmds;
|
|
|
|
cmds = cmds->next;
|
|
|
|
free(cmdst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (show_irq) {
|
|
|
|
irq = 0xdeadbeef;
|
|
|
|
retval = ioctl(fd, LPGETIRQ - offset, &irq);
|
|
|
|
if (retval == -1) {
|
|
|
|
perror("LPGETIRQ error");
|
|
|
|
exit(4);
|
|
|
|
}
|
|
|
|
if (irq == 0xdeadbeef) /* up to 1.1.77 will do this */
|
|
|
|
irq = retval;
|
|
|
|
if (irq)
|
|
|
|
printf("%s using IRQ %d\n", filename, irq);
|
|
|
|
else
|
|
|
|
printf("%s using polling\n", filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|