]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/tunelp.c
Merge branch 'zfs' of https://github.com/mihu/util-linux
[thirdparty/util-linux.git] / sys-utils / tunelp.c
1 /*
2 * Copyright (C) 1992-1997 Michael K. Johnson, johnsonm@redhat.com
3 *
4 * This file is licensed under the terms of the GNU General Public
5 * License, version 2, or any later version. See file COPYING for
6 * information on distribution conditions.
7 */
8
9 /*
10 * This command is deprecated. The utility is in maintenance mode,
11 * meaning we keep them in source tree for backward compatibility
12 * only. Do not waste time making this command better, unless the
13 * fix is about security or other very critical issue.
14 *
15 * See Documentation/deprecated.txt for more information.
16 */
17
18 /*
19 * $Log: tunelp.c,v $
20 * Revision 1.9 1998/06/08 19:37:11 janl
21 * Thus compiles tunelp with 2.1.103 kernels
22 *
23 * Revision 1.8 1997/07/06 00:14:06 aebr
24 * Fixes to silence -Wall.
25 *
26 * Revision 1.7 1997/06/20 16:10:38 janl
27 * tunelp refreshed from authors archive.
28 *
29 * Revision 1.9 1997/06/20 12:56:43 johnsonm
30 * Finished fixing license terms.
31 *
32 * Revision 1.8 1997/06/20 12:34:59 johnsonm
33 * Fixed copyright and license.
34 *
35 * Revision 1.7 1995/03/29 11:16:23 johnsonm
36 * TYPO fixed...
37 *
38 * Revision 1.6 1995/03/29 11:12:15 johnsonm
39 * Added third argument to ioctl needed with new kernels
40 *
41 * Revision 1.5 1995/01/13 10:33:43 johnsonm
42 * Chris's changes for new ioctl numbers and backwards compatibility
43 * and the reset ioctl.
44 *
45 * Revision 1.4 1995/01/03 17:42:14 johnsonm
46 * -s isn't supposed to take an argument; removed : after s in getopt...
47 *
48 * Revision 1.3 1995/01/03 07:36:49 johnsonm
49 * Fixed typo
50 *
51 * Revision 1.2 1995/01/03 07:33:44 johnsonm
52 * revisions for lp driver updates in Linux 1.1.76
53 *
54 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
55 * - added Native Language Support
56 *
57 * 1999-05-07 Merged LPTRUSTIRQ patch by Andrea Arcangeli (1998/11/29), aeb
58 *
59 */
60
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <getopt.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <sys/ioctl.h>
68 #include <sys/stat.h>
69 #include <sys/types.h>
70 #include <unistd.h>
71
72 #include "lp.h"
73 #include "nls.h"
74 #include "xalloc.h"
75 #include "closestream.h"
76
77 #define STRTOXX_EXIT_CODE 3
78 #define EXIT_LP_IO_ERR 4
79
80 #include "strutils.h"
81
82 struct command {
83 long op;
84 long val;
85 struct command *next;
86 };
87
88 static void __attribute__((__noreturn__)) print_usage(FILE *out)
89 {
90 fputs(USAGE_HEADER, out);
91 fprintf(out, _(" %s [options] <device>\n"), program_invocation_short_name);
92
93 fputs(USAGE_SEPARATOR, out);
94 fputs(_("Set various parameters for the line printer.\n"), out);
95
96 fputs(USAGE_OPTIONS, out);
97 fputs(_(" -i, --irq <num> specify parallel port irq\n"), out);
98 fputs(_(" -t, --time <ms> driver wait time in milliseconds\n"), out);
99 fputs(_(" -c, --chars <num> number of output characters before sleep\n"), out);
100 fputs(_(" -w, --wait <us> strobe wait in micro seconds\n"), out);
101 /* TRANSLATORS: do not translate <on|off> arguments. The
102 argument reader does not recognize locale, unless `on' is
103 exactly that very same string. */
104 fputs(_(" -a, --abort <on|off> abort on error\n"), out);
105 fputs(_(" -o, --check-status <on|off> check printer status before printing\n"), out);
106 fputs(_(" -C, --careful <on|off> extra checking to status check\n"), out);
107 fputs(_(" -s, --status query printer status\n"), out);
108 fputs(_(" -T, --trust-irq <on|off> make driver to trust irq\n"), out);
109 fputs(_(" -r, --reset reset the port\n"), out);
110 fputs(_(" -q, --print-irq <on|off> display current irq setting\n"), out);
111 fputs(USAGE_SEPARATOR, out);
112 fputs(USAGE_HELP, out);
113 fputs(USAGE_VERSION, out);
114 fprintf(out, USAGE_MAN_TAIL("tunelp(8)"));
115
116 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
117 }
118
119 int main(int argc, char **argv)
120 {
121 int c, fd, irq, status, show_irq, offset = 0, retval;
122 char *filename;
123 struct stat statbuf;
124 struct command *cmds, *cmdst;
125 static const struct option longopts[] = {
126 {"irq", required_argument, NULL, 'i'},
127 {"time", required_argument, NULL, 't'},
128 {"chars", required_argument, NULL, 'c'},
129 {"wait", required_argument, NULL, 'w'},
130 {"abort", required_argument, NULL, 'a'},
131 {"check-status", required_argument, NULL, 'o'},
132 {"careful", required_argument, NULL, 'C'},
133 {"status", no_argument, NULL, 's'},
134 {"trust-irq", required_argument, NULL, 'T'},
135 {"reset", no_argument, NULL, 'r'},
136 {"print-irq", required_argument, NULL, 'q'},
137 {"version", no_argument, NULL, 'V'},
138 {"help", no_argument, NULL, 'h'},
139 {NULL, 0, NULL, 0}
140 };
141
142 setlocale(LC_ALL, "");
143 bindtextdomain(PACKAGE, LOCALEDIR);
144 textdomain(PACKAGE);
145 atexit(close_stdout);
146
147 if (argc < 2)
148 print_usage(stderr);
149
150 cmdst = cmds = xmalloc(sizeof(struct command));
151 cmds->next = 0;
152
153 show_irq = 1;
154 while ((c = getopt_long(argc, argv, "t:c:w:a:i:ho:C:sq:rT:vV", longopts, NULL)) != -1) {
155 switch (c) {
156 case 'h':
157 print_usage(stdout);
158 break;
159 case 'i':
160 cmds->op = LPSETIRQ;
161 cmds->val = strtol_or_err(optarg, _("argument error"));
162 cmds->next = xmalloc(sizeof(struct command));
163 cmds = cmds->next;
164 cmds->next = 0;
165 break;
166 case 't':
167 cmds->op = LPTIME;
168 cmds->val = strtol_or_err(optarg, _("argument error"));
169 cmds->next = xmalloc(sizeof(struct command));
170 cmds = cmds->next;
171 cmds->next = 0;
172 break;
173 case 'c':
174 cmds->op = LPCHAR;
175 cmds->val = strtol_or_err(optarg, _("argument error"));
176 cmds->next = xmalloc(sizeof(struct command));
177 cmds = cmds->next;
178 cmds->next = 0;
179 break;
180 case 'w':
181 cmds->op = LPWAIT;
182 cmds->val = strtol_or_err(optarg, _("argument error"));
183 cmds->next = xmalloc(sizeof(struct command));
184 cmds = cmds->next;
185 cmds->next = 0;
186 break;
187 case 'a':
188 cmds->op = LPABORT;
189 cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
190 cmds->next = xmalloc(sizeof(struct command));
191 cmds = cmds->next;
192 cmds->next = 0;
193 break;
194 case 'q':
195 show_irq = parse_switch(optarg, _("argument error"), "on", "off", NULL);
196 break;
197 case 'o':
198 cmds->op = LPABORTOPEN;
199 cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
200 cmds->next = xmalloc(sizeof(struct command));
201 cmds = cmds->next;
202 cmds->next = 0;
203 break;
204 case 'C':
205 cmds->op = LPCAREFUL;
206 cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
207 cmds->next = xmalloc(sizeof(struct command));
208 cmds = cmds->next;
209 cmds->next = 0;
210 break;
211 case 's':
212 show_irq = 0;
213 cmds->op = LPGETSTATUS;
214 cmds->val = 0;
215 cmds->next = xmalloc(sizeof(struct command));
216 cmds = cmds->next;
217 cmds->next = 0;
218 break;
219 case 'r':
220 cmds->op = LPRESET;
221 cmds->val = 0;
222 cmds->next = xmalloc(sizeof(struct command));
223 cmds = cmds->next;
224 cmds->next = 0;
225 break;
226 case 'T':
227 /* Note: this will do the wrong thing on
228 * 2.0.36 when compiled under 2.2.x
229 */
230 cmds->op = LPTRUSTIRQ;
231 cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL);
232 cmds->next = xmalloc(sizeof(struct command));
233 cmds = cmds->next;
234 cmds->next = 0;
235 break;
236 case 'v':
237 case 'V':
238 printf(UTIL_LINUX_VERSION);
239 return EXIT_SUCCESS;
240 default:
241 print_usage(stderr);
242 }
243 }
244
245 if (optind != argc - 1)
246 print_usage(stderr);
247
248 filename = xstrdup(argv[optind]);
249 fd = open(filename, O_WRONLY | O_NONBLOCK, 0);
250 /* Need to open O_NONBLOCK in case ABORTOPEN is already set
251 * and printer is off or off-line or in an error condition.
252 * Otherwise we would abort...
253 */
254 if (fd < 0)
255 err(EXIT_FAILURE, "%s", filename);
256
257 if (fstat(fd, &statbuf))
258 err(EXIT_FAILURE, "%s: stat() failed", filename);
259
260 if (!S_ISCHR(statbuf.st_mode)) {
261 warnx(_("%s not an lp device"), filename);
262 print_usage(stderr);
263 }
264 /* Allow for binaries compiled under a new kernel to work on
265 * the old ones The irq argument to ioctl isn't touched by
266 * the old kernels, but we don't want to cause the kernel to
267 * complain if we are using a new kernel
268 */
269 if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0
270 && errno == EINVAL)
271 /* We don't understand the new ioctls */
272 offset = 0x0600;
273
274 cmds = cmdst;
275 while (cmds->next) {
276 if (cmds->op == LPGETSTATUS) {
277 status = 0xdeadbeef;
278 retval = ioctl(fd, LPGETSTATUS - offset, &status);
279 if (retval < 0)
280 warnx(_("LPGETSTATUS error"));
281 else {
282 if (status == (int)0xdeadbeef)
283 /* a few 1.1.7x kernels will do this */
284 status = retval;
285 printf(_("%s status is %d"), filename, status);
286 if (!(status & LP_PBUSY))
287 printf(_(", busy"));
288 if (!(status & LP_PACK))
289 printf(_(", ready"));
290 if ((status & LP_POUTPA))
291 printf(_(", out of paper"));
292 if ((status & LP_PSELECD))
293 printf(_(", on-line"));
294 if (!(status & LP_PERRORP))
295 printf(_(", error"));
296 printf("\n");
297 }
298 } else
299 if (ioctl(fd, cmds->op - offset, cmds->val) < 0)
300 warn(_("ioctl failed"));
301 cmdst = cmds;
302 cmds = cmds->next;
303 free(cmdst);
304 }
305
306 if (show_irq) {
307 irq = 0xdeadbeef;
308 retval = ioctl(fd, LPGETIRQ - offset, &irq);
309 if (retval == -1)
310 err(EXIT_LP_IO_ERR, _("LPGETIRQ error"));
311 if (irq == (int)0xdeadbeef)
312 /* up to 1.1.77 will do this */
313 irq = retval;
314 if (irq)
315 printf(_("%s using IRQ %d\n"), filename, irq);
316 else
317 printf(_("%s using polling\n"), filename);
318 }
319 free(filename);
320 close(fd);
321
322 return EXIT_SUCCESS;
323 }