]>
Commit | Line | Data |
---|---|---|
61319c6e SK |
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 | */ | |
6dbe3af9 | 8 | |
7d2600e2 SK |
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 | ||
d3e8f659 | 18 | /* |
726f69e2 | 19 | * $Log: tunelp.c,v $ |
2b6fc908 KZ |
20 | * Revision 1.9 1998/06/08 19:37:11 janl |
21 | * Thus compiles tunelp with 2.1.103 kernels | |
22 | * | |
fd6b7a7f KZ |
23 | * Revision 1.8 1997/07/06 00:14:06 aebr |
24 | * Fixes to silence -Wall. | |
726f69e2 | 25 | * |
fd6b7a7f KZ |
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 | |
6dbe3af9 KZ |
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 | * | |
b50945d4 | 54 | * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL> |
7eda085c KZ |
55 | * - added Native Language Support |
56 | * | |
57 | * 1999-05-07 Merged LPTRUSTIRQ patch by Andrea Arcangeli (1998/11/29), aeb | |
6dbe3af9 KZ |
58 | * |
59 | */ | |
60 | ||
61319c6e | 61 | #include <errno.h> |
7eda085c | 62 | #include <fcntl.h> |
a21108ba | 63 | #include <getopt.h> |
61319c6e | 64 | #include <stdio.h> |
66ee8158 | 65 | #include <stdlib.h> |
7eda085c | 66 | #include <string.h> |
61319c6e SK |
67 | #include <sys/ioctl.h> |
68 | #include <sys/stat.h> | |
69 | #include <sys/types.h> | |
70 | #include <unistd.h> | |
2ab428f6 | 71 | |
d52eb4bd SK |
72 | #include <linux/lp.h> |
73 | ||
7eda085c | 74 | #include "nls.h" |
efb8854f | 75 | #include "closestream.h" |
9c8b9fba | 76 | #include "strutils.h" |
6dbe3af9 | 77 | |
05691d9e | 78 | #define EXIT_LP_MALLOC 2 |
9c8b9fba | 79 | #define EXIT_LP_BADVAL 3 |
7e3c80a7 SK |
80 | #define EXIT_LP_IO_ERR 4 |
81 | ||
05691d9e RM |
82 | #define XALLOC_EXIT_CODE EXIT_LP_MALLOC |
83 | #include "xalloc.h" | |
84 | ||
6dbe3af9 | 85 | struct command { |
61319c6e SK |
86 | long op; |
87 | long val; | |
88 | struct command *next; | |
6dbe3af9 KZ |
89 | }; |
90 | ||
6e1eda6f | 91 | static void __attribute__((__noreturn__)) usage(void) |
61319c6e | 92 | { |
6e1eda6f | 93 | FILE *out = stdout; |
a21108ba SK |
94 | fputs(USAGE_HEADER, out); |
95 | fprintf(out, _(" %s [options] <device>\n"), program_invocation_short_name); | |
6dbe3af9 | 96 | |
451dbcfa BS |
97 | fputs(USAGE_SEPARATOR, out); |
98 | fputs(_("Set various parameters for the line printer.\n"), out); | |
99 | ||
a21108ba SK |
100 | fputs(USAGE_OPTIONS, out); |
101 | fputs(_(" -i, --irq <num> specify parallel port irq\n"), out); | |
102 | fputs(_(" -t, --time <ms> driver wait time in milliseconds\n"), out); | |
103 | fputs(_(" -c, --chars <num> number of output characters before sleep\n"), out); | |
104 | fputs(_(" -w, --wait <us> strobe wait in micro seconds\n"), out); | |
105 | /* TRANSLATORS: do not translate <on|off> arguments. The | |
106 | argument reader does not recognize locale, unless `on' is | |
107 | exactly that very same string. */ | |
108 | fputs(_(" -a, --abort <on|off> abort on error\n"), out); | |
109 | fputs(_(" -o, --check-status <on|off> check printer status before printing\n"), out); | |
110 | fputs(_(" -C, --careful <on|off> extra checking to status check\n"), out); | |
111 | fputs(_(" -s, --status query printer status\n"), out); | |
a21108ba SK |
112 | fputs(_(" -r, --reset reset the port\n"), out); |
113 | fputs(_(" -q, --print-irq <on|off> display current irq setting\n"), out); | |
114 | fputs(USAGE_SEPARATOR, out); | |
f45f3ec3 RM |
115 | printf(USAGE_HELP_OPTIONS(30)); |
116 | printf(USAGE_MAN_TAIL("tunelp(8)")); | |
a21108ba | 117 | |
6e1eda6f | 118 | exit(EXIT_SUCCESS); |
7eda085c | 119 | } |
6dbe3af9 | 120 | |
61319c6e SK |
121 | int main(int argc, char **argv) |
122 | { | |
123 | int c, fd, irq, status, show_irq, offset = 0, retval; | |
915b4bac | 124 | char *filename; |
61319c6e SK |
125 | struct stat statbuf; |
126 | struct command *cmds, *cmdst; | |
a21108ba SK |
127 | static const struct option longopts[] = { |
128 | {"irq", required_argument, NULL, 'i'}, | |
129 | {"time", required_argument, NULL, 't'}, | |
130 | {"chars", required_argument, NULL, 'c'}, | |
131 | {"wait", required_argument, NULL, 'w'}, | |
132 | {"abort", required_argument, NULL, 'a'}, | |
133 | {"check-status", required_argument, NULL, 'o'}, | |
134 | {"careful", required_argument, NULL, 'C'}, | |
135 | {"status", no_argument, NULL, 's'}, | |
136 | {"trust-irq", required_argument, NULL, 'T'}, | |
137 | {"reset", no_argument, NULL, 'r'}, | |
138 | {"print-irq", required_argument, NULL, 'q'}, | |
139 | {"version", no_argument, NULL, 'V'}, | |
140 | {"help", no_argument, NULL, 'h'}, | |
141 | {NULL, 0, NULL, 0} | |
142 | }; | |
6dbe3af9 | 143 | |
61319c6e SK |
144 | setlocale(LC_ALL, ""); |
145 | bindtextdomain(PACKAGE, LOCALEDIR); | |
146 | textdomain(PACKAGE); | |
2c308875 | 147 | close_stdout_atexit(); |
eb63b9b8 | 148 | |
9c8b9fba RM |
149 | strutils_set_exitcode(EXIT_LP_BADVAL); |
150 | ||
6e1eda6f RM |
151 | if (argc < 2) { |
152 | warnx(_("not enough arguments")); | |
153 | errtryhelp(EXIT_FAILURE); | |
154 | } | |
6dbe3af9 | 155 | |
61319c6e | 156 | cmdst = cmds = xmalloc(sizeof(struct command)); |
87918040 | 157 | cmds->next = NULL; |
6dbe3af9 | 158 | |
61319c6e | 159 | show_irq = 1; |
a21108ba | 160 | while ((c = getopt_long(argc, argv, "t:c:w:a:i:ho:C:sq:rT:vV", longopts, NULL)) != -1) { |
61319c6e | 161 | switch (c) { |
61319c6e SK |
162 | case 'i': |
163 | cmds->op = LPSETIRQ; | |
7e3c80a7 | 164 | cmds->val = strtol_or_err(optarg, _("argument error")); |
61319c6e SK |
165 | cmds->next = xmalloc(sizeof(struct command)); |
166 | cmds = cmds->next; | |
87918040 | 167 | cmds->next = NULL; |
61319c6e SK |
168 | break; |
169 | case 't': | |
170 | cmds->op = LPTIME; | |
7e3c80a7 | 171 | cmds->val = strtol_or_err(optarg, _("argument error")); |
61319c6e SK |
172 | cmds->next = xmalloc(sizeof(struct command)); |
173 | cmds = cmds->next; | |
87918040 | 174 | cmds->next = NULL; |
61319c6e SK |
175 | break; |
176 | case 'c': | |
177 | cmds->op = LPCHAR; | |
7e3c80a7 | 178 | cmds->val = strtol_or_err(optarg, _("argument error")); |
61319c6e SK |
179 | cmds->next = xmalloc(sizeof(struct command)); |
180 | cmds = cmds->next; | |
87918040 | 181 | cmds->next = NULL; |
61319c6e SK |
182 | break; |
183 | case 'w': | |
184 | cmds->op = LPWAIT; | |
7e3c80a7 | 185 | cmds->val = strtol_or_err(optarg, _("argument error")); |
61319c6e SK |
186 | cmds->next = xmalloc(sizeof(struct command)); |
187 | cmds = cmds->next; | |
87918040 | 188 | cmds->next = NULL; |
61319c6e SK |
189 | break; |
190 | case 'a': | |
191 | cmds->op = LPABORT; | |
7e5dd0e5 | 192 | cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL); |
61319c6e SK |
193 | cmds->next = xmalloc(sizeof(struct command)); |
194 | cmds = cmds->next; | |
87918040 | 195 | cmds->next = NULL; |
61319c6e SK |
196 | break; |
197 | case 'q': | |
7e5dd0e5 | 198 | show_irq = parse_switch(optarg, _("argument error"), "on", "off", NULL); |
a291c7ff | 199 | break; |
61319c6e SK |
200 | case 'o': |
201 | cmds->op = LPABORTOPEN; | |
7e5dd0e5 | 202 | cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL); |
61319c6e SK |
203 | cmds->next = xmalloc(sizeof(struct command)); |
204 | cmds = cmds->next; | |
87918040 | 205 | cmds->next = NULL; |
61319c6e SK |
206 | break; |
207 | case 'C': | |
208 | cmds->op = LPCAREFUL; | |
7e5dd0e5 | 209 | cmds->val = parse_switch(optarg, _("argument error"), "on", "off", NULL); |
61319c6e SK |
210 | cmds->next = xmalloc(sizeof(struct command)); |
211 | cmds = cmds->next; | |
87918040 | 212 | cmds->next = NULL; |
61319c6e SK |
213 | break; |
214 | case 's': | |
215 | show_irq = 0; | |
216 | cmds->op = LPGETSTATUS; | |
217 | cmds->val = 0; | |
218 | cmds->next = xmalloc(sizeof(struct command)); | |
219 | cmds = cmds->next; | |
87918040 | 220 | cmds->next = NULL; |
61319c6e | 221 | break; |
61319c6e SK |
222 | case 'r': |
223 | cmds->op = LPRESET; | |
224 | cmds->val = 0; | |
225 | cmds->next = xmalloc(sizeof(struct command)); | |
226 | cmds = cmds->next; | |
87918040 | 227 | cmds->next = NULL; |
61319c6e | 228 | break; |
2c308875 KZ |
229 | |
230 | case 'h': | |
231 | usage(); | |
61319c6e SK |
232 | case 'v': |
233 | case 'V': | |
2c308875 | 234 | print_version(EXIT_SUCCESS); |
61319c6e | 235 | default: |
677ec86c | 236 | errtryhelp(EXIT_FAILURE); |
61319c6e SK |
237 | } |
238 | } | |
7eda085c | 239 | |
6e1eda6f RM |
240 | if (optind != argc - 1) { |
241 | warnx(_("no device specified")); | |
242 | errtryhelp(EXIT_FAILURE); | |
243 | } | |
7eda085c | 244 | |
0b077eab | 245 | filename = xstrdup(argv[optind]); |
61319c6e SK |
246 | fd = open(filename, O_WRONLY | O_NONBLOCK, 0); |
247 | /* Need to open O_NONBLOCK in case ABORTOPEN is already set | |
248 | * and printer is off or off-line or in an error condition. | |
249 | * Otherwise we would abort... | |
250 | */ | |
915b4bac SK |
251 | if (fd < 0) |
252 | err(EXIT_FAILURE, "%s", filename); | |
7eda085c | 253 | |
97209c2b KZ |
254 | if (fstat(fd, &statbuf)) |
255 | err(EXIT_FAILURE, "%s: stat() failed", filename); | |
7eda085c | 256 | |
61319c6e | 257 | if (!S_ISCHR(statbuf.st_mode)) { |
915b4bac | 258 | warnx(_("%s not an lp device"), filename); |
6e1eda6f | 259 | errtryhelp(EXIT_FAILURE); |
61319c6e SK |
260 | } |
261 | /* Allow for binaries compiled under a new kernel to work on | |
262 | * the old ones The irq argument to ioctl isn't touched by | |
263 | * the old kernels, but we don't want to cause the kernel to | |
264 | * complain if we are using a new kernel | |
265 | */ | |
266 | if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0 | |
267 | && errno == EINVAL) | |
268 | /* We don't understand the new ioctls */ | |
269 | offset = 0x0600; | |
6dbe3af9 | 270 | |
61319c6e SK |
271 | cmds = cmdst; |
272 | while (cmds->next) { | |
61319c6e SK |
273 | if (cmds->op == LPGETSTATUS) { |
274 | status = 0xdeadbeef; | |
275 | retval = ioctl(fd, LPGETSTATUS - offset, &status); | |
276 | if (retval < 0) | |
915b4bac | 277 | warnx(_("LPGETSTATUS error")); |
61319c6e SK |
278 | else { |
279 | if (status == (int)0xdeadbeef) | |
280 | /* a few 1.1.7x kernels will do this */ | |
281 | status = retval; | |
282 | printf(_("%s status is %d"), filename, status); | |
283 | if (!(status & LP_PBUSY)) | |
284 | printf(_(", busy")); | |
285 | if (!(status & LP_PACK)) | |
286 | printf(_(", ready")); | |
287 | if ((status & LP_POUTPA)) | |
288 | printf(_(", out of paper")); | |
289 | if ((status & LP_PSELECD)) | |
290 | printf(_(", on-line")); | |
291 | if (!(status & LP_PERRORP)) | |
292 | printf(_(", error")); | |
293 | printf("\n"); | |
294 | } | |
295 | } else | |
915b4bac SK |
296 | if (ioctl(fd, cmds->op - offset, cmds->val) < 0) |
297 | warn(_("ioctl failed")); | |
61319c6e SK |
298 | cmdst = cmds; |
299 | cmds = cmds->next; | |
300 | free(cmdst); | |
301 | } | |
6dbe3af9 | 302 | |
61319c6e SK |
303 | if (show_irq) { |
304 | irq = 0xdeadbeef; | |
305 | retval = ioctl(fd, LPGETIRQ - offset, &irq); | |
915b4bac SK |
306 | if (retval == -1) |
307 | err(EXIT_LP_IO_ERR, _("LPGETIRQ error")); | |
61319c6e SK |
308 | if (irq == (int)0xdeadbeef) |
309 | /* up to 1.1.77 will do this */ | |
310 | irq = retval; | |
311 | if (irq) | |
312 | printf(_("%s using IRQ %d\n"), filename, irq); | |
313 | else | |
314 | printf(_("%s using polling\n"), filename); | |
315 | } | |
0b077eab | 316 | free(filename); |
61319c6e | 317 | close(fd); |
6dbe3af9 | 318 | |
130314aa | 319 | return EXIT_SUCCESS; |
6dbe3af9 | 320 | } |