-/****************************************************************************\
-* Copyright (C) 1992-1997 Michael K. Johnson, johnsonm@redhat.com *
-* *
-* This file is licensed under the terms of the GNU General *
-* Public License, version 2, or any later version. See file COPYING *
-* for information on distribution conditions. *
-\****************************************************************************/
+/*
+ * Copyright (C) 1992-1997 Michael K. Johnson, johnsonm@redhat.com
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License, version 2, or any later version. See file COPYING for
+ * information on distribution conditions.
+ */
-/* $Id: tunelp.c,v 1.9 1998/06/08 19:37:11 janl Exp $
+/*
+ * This command is deprecated. The utility is in maintenance mode,
+ * meaning we keep them in source tree for backward compatibility
+ * only. Do not waste time making this command better, unless the
+ * fix is about security or other very critical issue.
+ *
+ * See Documentation/deprecated.txt for more information.
+ */
+
+/*
* $Log: tunelp.c,v $
* Revision 1.9 1998/06/08 19:37:11 janl
* Thus compiles tunelp with 2.1.103 kernels
* Revision 1.2 1995/01/03 07:33:44 johnsonm
* revisions for lp driver updates in Linux 1.1.76
*
- * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
+ * 1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*
* 1999-05-07 Merged LPTRUSTIRQ patch by Andrea Arcangeli (1998/11/29), aeb
*
*/
-#include <unistd.h>
-#include <stdio.h>
+#include <errno.h>
#include <fcntl.h>
-/* #include <linux/fs.h> */
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <malloc.h>
-#include <string.h>
-#include <errno.h>
-#include "lp.h"
-#include "nls.h"
-
-struct command {
- long op;
- long val;
- struct command *next;
-};
+#include <unistd.h>
+#include <linux/lp.h>
-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"
- " -T [on|off] ]\n"),
- progname);
- exit (1);
-}
+#include "nls.h"
+#include "closestream.h"
+#include "strutils.h"
+#define EXIT_LP_MALLOC 2
+#define EXIT_LP_BADVAL 3
+#define EXIT_LP_IO_ERR 4
-void print_version(char *progname) {
- printf("%s %s\n", progname, UTIL_LINUX_VERSION);
-}
+#define XALLOC_EXIT_CODE EXIT_LP_MALLOC
+#include "xalloc.h"
+struct command {
+ long op;
+ long val;
+ struct command *next;
+};
-void *mylloc(long size) {
- void *ptr;
- if(!(ptr = (void*)malloc(size))) {
- perror(_("malloc error"));
- exit(2);
- }
- return ptr;
-}
-
-static char *progname;
+static void __attribute__((__noreturn__)) usage(void)
+{
+ FILE *out = stdout;
+ fputs(USAGE_HEADER, out);
+ fprintf(out, _(" %s [options] <device>\n"), program_invocation_short_name);
-long get_val(char *val) {
- long ret;
- if (!(sscanf(val, "%ld", &ret) == 1)) {
- fprintf(stderr, _("%s: bad value\n"), progname);
- exit(3);
- }
- return ret;
-}
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Set various parameters for the line printer.\n"), out);
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -i, --irq <num> specify parallel port irq\n"), out);
+ fputs(_(" -t, --time <ms> driver wait time in milliseconds\n"), out);
+ fputs(_(" -c, --chars <num> number of output characters before sleep\n"), out);
+ fputs(_(" -w, --wait <us> strobe wait in micro seconds\n"), out);
+ /* TRANSLATORS: do not translate <on|off> arguments. The
+ argument reader does not recognize locale, unless `on' is
+ exactly that very same string. */
+ fputs(_(" -a, --abort <on|off> abort on error\n"), out);
+ fputs(_(" -o, --check-status <on|off> check printer status before printing\n"), out);
+ fputs(_(" -C, --careful <on|off> extra checking to status check\n"), out);
+ fputs(_(" -s, --status query printer status\n"), out);
+ fputs(_(" -r, --reset reset the port\n"), out);
+ fputs(_(" -q, --print-irq <on|off> display current irq setting\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fprintf(out, USAGE_HELP_OPTIONS(30));
+ fprintf(out, USAGE_MAN_TAIL("tunelp(8)"));
-long get_onoff(char *val) {
- if (!strncasecmp("on", val, 2))
- return 1;
- return 0;
+ exit(EXIT_SUCCESS);
}
-int main (int argc, char ** argv) {
- int c, fd, irq, status, show_irq, offset = 0, retval;
- char *filename, *p;
- struct stat statbuf;
- struct command *cmds, *cmdst;
-
- progname = argv[0];
- if ((p = strrchr(progname, '/')) != NULL)
- progname = p+1;
+int main(int argc, char **argv)
+{
+ int c, fd, irq, status, show_irq, offset = 0, retval;
+ char *filename;
+ struct stat statbuf;
+ struct command *cmds, *cmdst;
+ static const struct option longopts[] = {
+ {"irq", required_argument, NULL, 'i'},
+ {"time", required_argument, NULL, 't'},
+ {"chars", required_argument, NULL, 'c'},
+ {"wait", required_argument, NULL, 'w'},
+ {"abort", required_argument, NULL, 'a'},
+ {"check-status", required_argument, NULL, 'o'},
+ {"careful", required_argument, NULL, 'C'},
+ {"status", no_argument, NULL, 's'},
+ {"trust-irq", required_argument, NULL, 'T'},
+ {"reset", no_argument, NULL, 'r'},
+ {"print-irq", required_argument, NULL, 'q'},
+ {"version", no_argument, NULL, 'V'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ close_stdout_atexit();
- if (argc < 2) print_usage(progname);
+ strutils_set_exitcode(EXIT_LP_BADVAL);
- cmdst = cmds = mylloc(sizeof(struct command));
- cmds->next = 0;
+ if (argc < 2) {
+ warnx(_("not enough arguments"));
+ errtryhelp(EXIT_FAILURE);
+ }
- show_irq = 1;
- while ((c = getopt(argc, argv, "t:c:w:a:i:ho:C:sq:rT:vV")) != 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
-#ifdef LPTRUSTIRQ
- case 'T':
- /* Note: this will do the wrong thing on 2.0.36 when compiled under 2.2.x */
- cmds->op = LPTRUSTIRQ;
- cmds->val = get_onoff(optarg);
- cmds->next = mylloc(sizeof(struct command));
- cmds = cmds->next; cmds->next = 0;
- break;
-#endif
- case 'v':
- case 'V':
- print_version(progname);
- exit(0);
- default:
- print_usage(progname);
- }
- }
+ cmdst = cmds = xmalloc(sizeof(struct command));
+ cmds->next = NULL;
- if (optind != argc-1)
- print_usage(progname);
+ show_irq = 1;
+ while ((c = getopt_long(argc, argv, "t:c:w:a:i:ho:C:sq:rT:vV", longopts, NULL)) != -1) {
+ switch (c) {
+ case 'i':
+ cmds->op = LPSETIRQ;
+ cmds->val = strtol_or_err(optarg, _("argument error"));
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 't':
+ cmds->op = LPTIME;
+ cmds->val = strtol_or_err(optarg, _("argument error"));
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 'c':
+ cmds->op = LPCHAR;
+ cmds->val = strtol_or_err(optarg, _("argument error"));
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 'w':
+ cmds->op = LPWAIT;
+ cmds->val = strtol_or_err(optarg, _("argument error"));
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 'a':
+ cmds->op = LPABORT;
+ cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 'q':
+ show_irq = parse_switch(optarg, _("argument error"), "on", "off", NULL);
+ break;
+ case 'o':
+ cmds->op = LPABORTOPEN;
+ cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 'C':
+ cmds->op = LPCAREFUL;
+ cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 's':
+ show_irq = 0;
+ cmds->op = LPGETSTATUS;
+ cmds->val = 0;
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
+ case 'r':
+ cmds->op = LPRESET;
+ cmds->val = 0;
+ cmds->next = xmalloc(sizeof(struct command));
+ cmds = cmds->next;
+ cmds->next = NULL;
+ break;
- filename = strdup(argv[optind]);
- 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(filename);
- return -1;
- }
+ case 'h':
+ usage();
+ case 'v':
+ case 'V':
+ print_version(EXIT_SUCCESS);
+ default:
+ errtryhelp(EXIT_FAILURE);
+ }
+ }
- fstat(fd, &statbuf);
+ if (optind != argc - 1) {
+ warnx(_("no device specified"));
+ errtryhelp(EXIT_FAILURE);
+ }
- if(!S_ISCHR(statbuf.st_mode)) {
- printf(_("%s: %s not an lp device.\n"), argv[0], filename);
- print_usage(progname);
- }
+ filename = xstrdup(argv[optind]);
+ 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)
+ err(EXIT_FAILURE, "%s", filename);
- /* Allow for binaries compiled under a new kernel to work on the old ones */
- /* The irq argument to ioctl isn't touched by the old kernels, but we don't */
- /* want to cause the kernel to complain if we are using a new kernel */
- if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0 && errno == EINVAL)
- offset = 0x0600; /* We don't understand the new ioctls */
+ if (fstat(fd, &statbuf))
+ err(EXIT_FAILURE, "%s: stat() failed", filename);
- 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 (!S_ISCHR(statbuf.st_mode)) {
+ warnx(_("%s not an lp device"), filename);
+ errtryhelp(EXIT_FAILURE);
+ }
+ /* Allow for binaries compiled under a new kernel to work on
+ * the old ones The irq argument to ioctl isn't touched by
+ * the old kernels, but we don't want to cause the kernel to
+ * complain if we are using a new kernel
+ */
+ if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0
+ && errno == EINVAL)
+ /* We don't understand the new ioctls */
+ offset = 0x0600;
- 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);
- }
+ cmds = cmdst;
+ while (cmds->next) {
+ if (cmds->op == LPGETSTATUS) {
+ status = 0xdeadbeef;
+ retval = ioctl(fd, LPGETSTATUS - offset, &status);
+ if (retval < 0)
+ warnx(_("LPGETSTATUS error"));
+ else {
+ if (status == (int)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 if (ioctl(fd, cmds->op - offset, cmds->val) < 0)
+ warn(_("ioctl failed"));
+ cmdst = cmds;
+ cmds = cmds->next;
+ free(cmdst);
+ }
- close(fd);
+ if (show_irq) {
+ irq = 0xdeadbeef;
+ retval = ioctl(fd, LPGETIRQ - offset, &irq);
+ if (retval == -1)
+ err(EXIT_LP_IO_ERR, _("LPGETIRQ error"));
+ if (irq == (int)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);
+ }
+ free(filename);
+ close(fd);
- return 0;
+ return EXIT_SUCCESS;
}