]> git.ipfire.org Git - thirdparty/util-linux.git/blame - term-utils/setterm.c
setterm: convert various constant number definitions to enums
[thirdparty/util-linux.git] / term-utils / setterm.c
CommitLineData
6dbe3af9
KZ
1/* setterm.c, set terminal attributes.
2 *
3 * Copyright (C) 1990 Gordon Irlam (gordoni@cs.ua.oz.au). Conditions of use,
4 * modification, and redistribution are contained in the file COPYRIGHT that
5 * forms part of this distribution.
6 *
7 * Adaption to Linux by Peter MacDonald.
8 *
9 * Enhancements by Mika Liljeberg (liljeber@cs.Helsinki.FI)
10 *
fd6b7a7f
KZ
11 * Beep modifications by Christophe Jolif (cjolif@storm.gatelink.fr.net)
12 *
13 * Sanity increases by Cafeine Addict [sic].
14 *
eb63b9b8 15 * Powersave features by todd j. derr <tjd@wordsmith.org>
fd6b7a7f
KZ
16 *
17 * Converted to terminfo by Kars de Jong (jongk@cs.utwente.nl)
6dbe3af9 18 *
b50945d4 19 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
7eda085c
KZ
20 * - added Native Language Support
21 *
22 *
6dbe3af9
KZ
23 * Syntax:
24 *
25 * setterm
26 * [ -term terminal_name ]
27 * [ -reset ]
28 * [ -initialize ]
29 * [ -cursor [on|off] ]
6dbe3af9
KZ
30 * [ -repeat [on|off] ]
31 * [ -appcursorkeys [on|off] ]
32 * [ -linewrap [on|off] ]
33 * [ -snow [on|off] ]
34 * [ -softscroll [on|off] ]
35 * [ -defaults ]
36 * [ -foreground black|red|green|yellow|blue|magenta|cyan|white|default ]
37 * [ -background black|red|green|yellow|blue|magenta|cyan|white|default ]
38 * [ -ulcolor black|grey|red|green|yellow|blue|magenta|cyan|white ]
39 * [ -ulcolor bright red|green|yellow|blue|magenta|cyan|white ]
40 * [ -hbcolor black|grey|red|green|yellow|blue|magenta|cyan|white ]
41 * [ -hbcolor bright red|green|yellow|blue|magenta|cyan|white ]
42 * [ -inversescreen [on|off] ]
43 * [ -bold [on|off] ]
44 * [ -half-bright [on|off] ]
45 * [ -blink [on|off] ]
46 * [ -reverse [on|off] ]
47 * [ -underline [on|off] ]
48 * [ -store ]
49 * [ -clear [ all|rest ] ]
50 * [ -tabs [tab1 tab2 tab3 ... ] ] (tabn = 1-160)
51 * [ -clrtabs [ tab1 tab2 tab3 ... ] (tabn = 1-160)
52 * [ -regtabs [1-160] ]
5c55d9bf 53 * [ -blank [0-60|force|poke|] ]
6dbe3af9
KZ
54 * [ -dump [1-NR_CONS ] ]
55 * [ -append [1-NR_CONS ] ]
56 * [ -file dumpfilename ]
57 * [ -standout [attr] ]
58 * [ -msg [on|off] ]
59 * [ -msglevel [0-8] ]
fd6b7a7f
KZ
60 * [ -powersave [on|vsync|hsync|powerdown|off] ]
61 * [ -powerdown [0-60] ]
62 * [ -blength [0-2000] ]
63 * [ -bfreq freq ]
faa0548d
SK
64 * [ -version ]
65 * [ -help ]
6dbe3af9
KZ
66 *
67 *
68 * Semantics:
69 *
fd6b7a7f 70 * Setterm writes to standard output a character string that will
871ffd09 71 * invoke the specified terminal capabilities. Where possible
fd6b7a7f
KZ
72 * terminfo is consulted to find the string to use. Some options
73 * however do not correspond to a terminfo capability. In this case if
74 * the terminal type is "con*", or "linux*" the string that invokes
75 * the specified capabilities on the PC Linux virtual console driver
76 * is output. Options that are not implemented by the terminal are
77 * ignored.
6dbe3af9
KZ
78 *
79 * The following options are non-obvious.
80 *
81 * -term can be used to override the TERM environment variable.
82 *
83 * -reset displays the terminal reset string, which typically resets the
84 * terminal to its power on state.
85 *
86 * -initialize displays the terminal initialization string, which typically
87 * sets the terminal's rendering options, and other attributes to the
88 * default values.
89 *
90 * -default sets the terminal's rendering options to the default values.
91 *
92 * -store stores the terminal's current rendering options as the default
fd6b7a7f 93 * values. */
6dbe3af9 94
6dbe3af9 95#include <stdio.h>
22853e4a 96#include <stdlib.h>
fd6b7a7f 97#include <errno.h>
6dbe3af9 98#include <ctype.h>
6dbe3af9
KZ
99#include <unistd.h>
100#include <termios.h>
101#include <string.h>
fd6b7a7f 102#include <fcntl.h>
bfc4331b 103
5c36a0eb
KZ
104#ifndef NCURSES_CONST
105#define NCURSES_CONST const /* define before including term.h */
106#endif
48d7b13a 107#ifdef HAVE_NCURSES_H
fd6b7a7f 108#include <ncurses.h>
b6e899d9 109#elif defined(HAVE_NCURSES_NCURSES_H)
48d7b13a 110#include <ncurses/ncurses.h>
fd6b7a7f 111#endif
bfc4331b
MF
112/* must include after ncurses.h */
113#include <term.h>
48d7b13a 114
a5a16c68 115#include <sys/param.h> /* for MAXPATHLEN */
fd6b7a7f
KZ
116#include <sys/ioctl.h>
117#include <sys/time.h>
5c55d9bf
ST
118#ifdef HAVE_LINUX_TIOCL_H
119#include <linux/tiocl.h>
120#endif
b6e899d9
KZ
121
122#include "c.h"
87f3feac 123#include "xalloc.h"
7eda085c 124#include "nls.h"
cdd2a8c3 125#include "closestream.h"
6dbe3af9 126
23e0d15b 127#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ < 5
fd6b7a7f
KZ
128#ifndef __alpha__
129# include <linux/unistd.h>
130#define __NR_klogctl __NR_syslog
131_syscall3(int, klogctl, int, type, char*, buf, int, len);
132#else /* __alpha__ */
133#define klogctl syslog
134#endif
135#endif
2b6fc908 136extern int klogctl(int type, char *buf, int len);
6dbe3af9 137
fd6b7a7f 138/* Constants. */
6dbe3af9 139
261f1423
SK
140/* Non-standard return values. */
141#define EXIT_DUMPFILE -1
142
6dbe3af9 143/* Colors. */
010f219d
SK
144enum {
145 BLACK = 0,
146 RED,
147 GREEN,
148 YELLOW,
149 BLUE,
150 MAGENTA,
151 CYAN,
152 WHITE,
153 GREY,
154 DEFAULT
155};
6dbe3af9 156
5c55d9bf 157/* Blank commands */
010f219d
SK
158enum {
159 BLANKSCREEN = -1,
160 UNBLANKSCREEN = -2,
161 BLANKEDSCREEN = -3
162};
5c55d9bf
ST
163
164/* <linux/tiocl.h> fallback */
165#ifndef TIOCL_BLANKSCREEN
010f219d
SK
166enum {
167 TIOCL_UNBLANKSCREEN = 4, /* unblank screen */
168 TIOCL_SETVESABLANK = 10, /* set vesa blanking mode */
169 TIOCL_BLANKSCREEN = 14, /* keep screen blank even if a key is pressed */
170 TIOCL_BLANKEDSCREEN = 15 /* return which vt was blanked */
171};
5c55d9bf
ST
172#endif
173
6dbe3af9 174/* Option flags. Set if the option is to be invoked. */
eb63b9b8 175int opt_term, opt_reset, opt_initialize, opt_cursor;
45656c9f 176int opt_linewrap, opt_default, opt_foreground;
6dbe3af9 177int opt_background, opt_bold, opt_blink, opt_reverse, opt_underline;
45656c9f 178int opt_store, opt_clear, opt_blank, opt_snap, opt_snapfile;
6dbe3af9
KZ
179int opt_append, opt_ulcolor, opt_hbcolor, opt_halfbright, opt_repeat;
180int opt_tabs, opt_clrtabs, opt_regtabs, opt_appcursorkeys, opt_inversescreen;
fd6b7a7f
KZ
181int opt_msg, opt_msglevel, opt_powersave, opt_powerdown;
182int opt_blength, opt_bfreq;
6dbe3af9
KZ
183
184/* Option controls. The variable names have been contracted to ensure
185 * uniqueness.
186 */
187char *opt_te_terminal_name; /* Terminal name. */
45656c9f 188int opt_cu_on, opt_li_on, opt_bo_on, opt_hb_on, opt_bl_on;
6dbe3af9 189int opt_re_on, opt_un_on, opt_rep_on, opt_appck_on, opt_invsc_on;
fd6b7a7f 190int opt_msg_on; /* Boolean switches. */
6dbe3af9
KZ
191int opt_fo_color, opt_ba_color; /* Colors. */
192int opt_ul_color, opt_hb_color;
193int opt_cl_all; /* Clear all or rest. */
194int opt_bl_min; /* Blank screen. */
fd6b7a7f
KZ
195int opt_blength_l;
196int opt_bfreq_f;
a5a16c68 197int opt_sn_num; /* Snap screen. */
6dbe3af9
KZ
198int opt_rt_len; /* regular tab length */
199int opt_tb_array[161]; /* Array for tab list */
200int opt_msglevel_num;
fd6b7a7f 201int opt_ps_mode, opt_pd_min; /* powersave mode/powerdown time */
6dbe3af9 202
29715436 203char opt_sn_name[PATH_MAX + 1] = "screen.dump";
6dbe3af9 204
22853e4a 205static void screendump(int vcnum, FILE *F);
fd6b7a7f 206
6dbe3af9
KZ
207/* Command line parsing routines.
208 *
209 * Note that it is an error for a given option to be invoked more than once.
210 */
211
22853e4a 212static void
4d9e37bf 213parse_term(int argc, char **argv, int *option, char **ttyname, int *bad_arg) {
22853e4a
KZ
214 /* argc: Number of arguments for this option. */
215 /* argv: Arguments for this option. */
216 /* option: Term flag to set. */
4d9e37bf 217 /* ttyname: Terminal name to set. */
22853e4a
KZ
218 /* bad_arg: Set to true if an error is detected. */
219
6dbe3af9
KZ
220/* Parse a -term specification. */
221
22853e4a
KZ
222 if (argc != 1 || *option)
223 *bad_arg = TRUE;
224 *option = TRUE;
225 if (argc == 1)
4d9e37bf 226 *ttyname = argv[0];
6dbe3af9
KZ
227}
228
22853e4a 229static void
172ba4f2 230parse_none(int argc, char **argv __attribute__ ((__unused__)), int *option, int *bad_arg) {
22853e4a
KZ
231 /* argc: Number of arguments for this option. */
232 /* argv: Arguments for this option. */
233 /* option: Term flag to set. */
234 /* bad_arg: Set to true if an error is detected. */
235
6dbe3af9
KZ
236/* Parse a parameterless specification. */
237
22853e4a
KZ
238 if (argc != 0 || *option)
239 *bad_arg = TRUE;
240 *option = TRUE;
6dbe3af9
KZ
241}
242
22853e4a
KZ
243static void
244parse_switch(int argc, char **argv, int *option, int *opt_on, int *bad_arg) {
245 /* argc: Number of arguments for this option. */
246 /* argv: Arguments for this option. */
247 /* option: Option flag to set. */
248 /* opt_on: Boolean option switch to set or reset. */
249 /* bad_arg: Set to true if an error is detected. */
250
6dbe3af9
KZ
251/* Parse a boolean (on/off) specification. */
252
22853e4a 253 if (argc > 1 || *option)
6dbe3af9 254 *bad_arg = TRUE;
22853e4a
KZ
255 *option = TRUE;
256 if (argc == 1) {
257 if (strcmp(argv[0], "on") == 0)
258 *opt_on = TRUE;
259 else if (strcmp(argv[0], "off") == 0)
260 *opt_on = FALSE;
261 else
262 *bad_arg = TRUE;
263 } else {
264 *opt_on = TRUE;
265 }
6dbe3af9
KZ
266}
267
22853e4a
KZ
268static void
269par_color(int argc, char **argv, int *option, int *opt_color, int *bad_arg) {
270 /* argc: Number of arguments for this option. */
271 /* argv: Arguments for this option. */
272 /* option: Color flag to set. */
273 /* opt_color: Color to set. */
274 /* bad_arg: Set to true if an error is detected. */
275
6dbe3af9
KZ
276/* Parse a -foreground or -background specification. */
277
22853e4a
KZ
278 if (argc != 1 || *option)
279 *bad_arg = TRUE;
280 *option = TRUE;
281 if (argc == 1) {
282 if (strcmp(argv[0], "black") == 0)
283 *opt_color = BLACK;
284 else if (strcmp(argv[0], "red") == 0)
285 *opt_color = RED;
286 else if (strcmp(argv[0], "green") == 0)
287 *opt_color = GREEN;
288 else if (strcmp(argv[0], "yellow") == 0)
289 *opt_color = YELLOW;
290 else if (strcmp(argv[0], "blue") == 0)
291 *opt_color = BLUE;
292 else if (strcmp(argv[0], "magenta") == 0)
293 *opt_color = MAGENTA;
294 else if (strcmp(argv[0], "cyan") == 0)
295 *opt_color = CYAN;
296 else if (strcmp(argv[0], "white") == 0)
297 *opt_color = WHITE;
298 else if (strcmp(argv[0], "default") == 0)
299 *opt_color = DEFAULT;
300 else if (isdigit(argv[0][0]))
301 *opt_color = atoi(argv[0]);
b6e899d9 302 else
22853e4a 303 *bad_arg = TRUE;
b6e899d9 304
010f219d 305 if(*opt_color < BLACK || DEFAULT < *opt_color || *opt_color == GREY)
22853e4a
KZ
306 *bad_arg = TRUE;
307 }
6dbe3af9
KZ
308}
309
22853e4a
KZ
310static void
311par_color2(int argc, char **argv, int *option, int *opt_color, int *bad_arg) {
312 /* argc: Number of arguments for this option. */
313 /* argv: Arguments for this option. */
314 /* option: Color flag to set. */
315 /* opt_color: Color to set. */
316 /* bad_arg: Set to true if an error is detected. */
317
6dbe3af9
KZ
318/* Parse a -ulcolor or -hbcolor specification. */
319
22853e4a 320 if (!argc || argc > 2 || *option)
6dbe3af9 321 *bad_arg = TRUE;
22853e4a
KZ
322 *option = TRUE;
323 *opt_color = 0;
324 if (argc == 2) {
325 if (strcmp(argv[0], "bright") == 0)
010f219d 326 *opt_color = GREY;
22853e4a
KZ
327 else {
328 *bad_arg = TRUE;
329 return;
330 }
6dbe3af9 331 }
22853e4a
KZ
332 if (argc) {
333 if (strcmp(argv[argc-1], "black") == 0) {
334 if(*opt_color)
335 *bad_arg = TRUE;
336 else
337 *opt_color = BLACK;
338 } else if (strcmp(argv[argc-1], "grey") == 0) {
339 if(*opt_color)
340 *bad_arg = TRUE;
341 else
342 *opt_color = GREY;
343 } else if (strcmp(argv[argc-1], "red") == 0)
344 *opt_color |= RED;
345 else if (strcmp(argv[argc-1], "green") == 0)
346 *opt_color |= GREEN;
347 else if (strcmp(argv[argc-1], "yellow") == 0)
348 *opt_color |= YELLOW;
349 else if (strcmp(argv[argc-1], "blue") == 0)
350 *opt_color |= BLUE;
351 else if (strcmp(argv[argc-1], "magenta") == 0)
352 *opt_color |= MAGENTA;
353 else if (strcmp(argv[argc-1], "cyan") == 0)
354 *opt_color |= CYAN;
355 else if (strcmp(argv[argc-1], "white") == 0)
356 *opt_color |= WHITE;
357 else if (isdigit(argv[argc-1][0]))
358 *opt_color = atoi(argv[argc-1]);
b6e899d9 359 else
6dbe3af9 360 *bad_arg = TRUE;
010f219d 361 if(*opt_color < BLACK || DEFAULT < *opt_color )
6dbe3af9 362 *bad_arg = TRUE;
22853e4a 363 }
6dbe3af9
KZ
364}
365
22853e4a
KZ
366static void
367parse_clear(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
368 /* argc: Number of arguments for this option. */
369 /* argv: Arguments for this option. */
370 /* option: Clear flag to set. */
371 /* opt_all: Clear all switch to set or reset. */
372 /* bad_arg: Set to true if an error is detected. */
373
6dbe3af9
KZ
374/* Parse a -clear specification. */
375
22853e4a 376 if (argc > 1 || *option)
6dbe3af9 377 *bad_arg = TRUE;
22853e4a
KZ
378 *option = TRUE;
379 if (argc == 1) {
380 if (strcmp(argv[0], "all") == 0)
381 *opt_all = TRUE;
382 else if (strcmp(argv[0], "rest") == 0)
383 *opt_all = FALSE;
384 else
385 *bad_arg = TRUE;
386 } else {
387 *opt_all = TRUE;
388 }
6dbe3af9
KZ
389}
390
22853e4a
KZ
391static void
392parse_blank(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
393 /* argc: Number of arguments for this option. */
394 /* argv: Arguments for this option. */
395 /* option: Clear flag to set. */
396 /* opt_all: Clear all switch to set or reset. */
397 /* bad_arg: Set to true if an error is detected. */
398
fd6b7a7f 399/* Parse a -blank specification. */
6dbe3af9 400
22853e4a 401 if (argc > 1 || *option)
6dbe3af9 402 *bad_arg = TRUE;
22853e4a
KZ
403 *option = TRUE;
404 if (argc == 1) {
5c55d9bf
ST
405 if (!strcmp(argv[0], "force"))
406 *opt_all = BLANKSCREEN;
407 else if (!strcmp(argv[0], "poke"))
408 *opt_all = UNBLANKSCREEN;
409 else {
410 *opt_all = atoi(argv[0]);
411 if ((*opt_all > 60) || (*opt_all < 0))
412 *bad_arg = TRUE;
413 }
22853e4a 414 } else {
5c55d9bf 415 *opt_all = BLANKEDSCREEN;
22853e4a 416 }
6dbe3af9
KZ
417}
418
22853e4a
KZ
419static void
420parse_powersave(int argc, char **argv, int *option, int *opt_mode, int *bad_arg) {
421 /* argc: Number of arguments for this option. */
422 /* argv: Arguments for this option. */
423 /* option: powersave flag to set. */
424 /* opt_mode: Powersaving mode, defined in vesa_blank.c */
425 /* bad_arg: Set to true if an error is detected. */
426
fd6b7a7f
KZ
427/* Parse a -powersave mode specification. */
428
22853e4a 429 if (argc > 1 || *option)
fd6b7a7f 430 *bad_arg = TRUE;
22853e4a
KZ
431 *option = TRUE;
432 if (argc == 1) {
433 if (strcmp(argv[0], "on") == 0)
434 *opt_mode = 1;
435 else if (strcmp(argv[0], "vsync") == 0)
436 *opt_mode = 1;
437 else if (strcmp(argv[0], "hsync") == 0)
438 *opt_mode = 2;
439 else if (strcmp(argv[0], "powerdown") == 0)
440 *opt_mode = 3;
441 else if (strcmp(argv[0], "off") == 0)
442 *opt_mode = 0;
443 else
444 *bad_arg = TRUE;
445 } else {
446 *opt_mode = 0;
447 }
fd6b7a7f
KZ
448}
449
22853e4a
KZ
450static void
451parse_msglevel(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
452 /* argc: Number of arguments for this option. */
453 /* argv: Arguments for this option. */
454 /* option: Clear flag to set. */
455 /* opt_all: Clear all switch to set or reset. */
456 /* bad_arg: Set to true if an error is detected. */
457
458 if (argc > 1 || *option)
6dbe3af9 459 *bad_arg = TRUE;
22853e4a
KZ
460 *option = TRUE;
461 if (argc == 1) {
462 *opt_all = atoi(argv[0]);
463 if (*opt_all < 0 || *opt_all > 8)
464 *bad_arg = TRUE;
465 } else {
466 *opt_all = -1;
467 }
6dbe3af9
KZ
468}
469
22853e4a
KZ
470static void
471parse_snap(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
472 /* argc: Number of arguments for this option. */
473 /* argv: Arguments for this option. */
474 /* option: Clear flag to set. */
475 /* opt_all: Clear all switch to set or reset. */
476 /* bad_arg: Set to true if an error is detected. */
477
fd6b7a7f 478/* Parse a -dump or -append specification. */
6dbe3af9 479
22853e4a 480 if (argc > 1 || *option)
6dbe3af9 481 *bad_arg = TRUE;
22853e4a
KZ
482 *option = TRUE;
483 if (argc == 1) {
484 *opt_all = atoi(argv[0]);
485 if ((*opt_all <= 0))
486 *bad_arg = TRUE;
487 } else {
488 *opt_all = 0;
489 }
6dbe3af9
KZ
490}
491
22853e4a
KZ
492static void
493parse_snapfile(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
494 /* argc: Number of arguments for this option. */
495 /* argv: Arguments for this option. */
496 /* option: Clear flag to set. */
497 /* opt_all: Clear all switch to set or reset. */
498 /* bad_arg: Set to true if an error is detected. */
499
fd6b7a7f 500/* Parse a -file specification. */
6dbe3af9 501
22853e4a
KZ
502 if (argc != 1 || *option)
503 *bad_arg = TRUE;
504 *option = TRUE;
29715436 505 memset(opt_all, 0, PATH_MAX + 1);
22853e4a 506 if (argc == 1)
29715436 507 strncpy((char *)opt_all, argv[0], PATH_MAX);
6dbe3af9
KZ
508}
509
22853e4a
KZ
510static void
511parse_tabs(int argc, char **argv, int *option, int *tab_array, int *bad_arg) {
512 /* argc: Number of arguments for this option. */
513 /* argv: Arguments for this option. */
514 /* option: Clear flag to set. */
515 /* tab_array: Array of tabs */
516 /* bad_arg: Set to true if an error is detected. */
517
518 if (*option || argc > 160)
519 *bad_arg = TRUE;
520 *option = TRUE;
521 tab_array[argc] = -1;
522 while(argc--) {
523 tab_array[argc] = atoi(argv[argc]);
524 if(tab_array[argc] < 1 || tab_array[argc] > 160) {
525 *bad_arg = TRUE;
526 return;
527 }
528 }
6dbe3af9
KZ
529}
530
22853e4a
KZ
531static void
532parse_clrtabs(int argc, char **argv, int *option, int *tab_array, int *bad_arg) {
533 /* argc: Number of arguments for this option. */
534 /* argv: Arguments for this option. */
535 /* option: Clear flag to set. */
536 /* tab_array: Array of tabs */
537 /* bad_arg: Set to true if an error is detected. */
538
539 if (*option || argc > 160)
540 *bad_arg = TRUE;
541 *option = TRUE;
542 if(argc == 0) {
543 tab_array[0] = -1;
544 return;
545 }
546 tab_array[argc] = -1;
547 while(argc--) {
548 tab_array[argc] = atoi(argv[argc]);
549 if(tab_array[argc] < 1 || tab_array[argc] > 160) {
550 *bad_arg = TRUE;
551 return;
552 }
553 }
6dbe3af9
KZ
554}
555
22853e4a
KZ
556static void
557parse_regtabs(int argc, char **argv, int *option, int *opt_len, int *bad_arg) {
558 /* argc: Number of arguments for this option. */
559 /* argv: Arguments for this option. */
560 /* option: Clear flag to set. */
561 /* opt_len: Regular tab length. */
562 /* bad_arg: Set to true if an error is detected. */
563
564 if (*option || argc > 1)
565 *bad_arg = TRUE;
566 *option = TRUE;
567 if(argc == 0) {
568 *opt_len = 8;
569 return;
570 }
571 *opt_len = atoi(argv[0]);
572 if(*opt_len < 1 || *opt_len > 160) {
573 *bad_arg = TRUE;
574 return;
575 }
6dbe3af9
KZ
576}
577
fd6b7a7f 578
22853e4a
KZ
579static void
580parse_blength(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
581 /* argc: Number of arguments for this option. */
582 /* argv: Arguments for this option. */
583 /* option: Clear flag to set. */
584 /* opt_all */
585 /* bad_arg: Set to true if an error is detected. */
586
fd6b7a7f
KZ
587/* Parse -blength specification. */
588
22853e4a 589 if (argc > 1 || *option)
fd6b7a7f 590 *bad_arg = TRUE;
22853e4a
KZ
591 *option = TRUE;
592 if (argc == 1) {
593 *opt_all = atoi(argv[0]);
594 if (*opt_all > 2000)
595 *bad_arg = TRUE;
596 } else {
597 *opt_all = 0;
598 }
fd6b7a7f
KZ
599}
600
22853e4a
KZ
601static void
602parse_bfreq(int argc, char **argv, int *option, int *opt_all, int *bad_arg) {
603 /* argc: Number of arguments for this option. */
604 /* argv: Arguments for this option. */
605 /* option: Clear flag to set. */
606 /* opt_all */
607 /* bad_arg: Set to true if an error is detected. */
608
fd6b7a7f
KZ
609/* Parse -bfreq specification. */
610
22853e4a
KZ
611 if (argc > 1 || *option)
612 *bad_arg = TRUE;
613 *option = TRUE;
614 if (argc == 1) {
615 *opt_all = atoi(argv[0]);
616 } else {
617 *opt_all = 0;
618 }
fd6b7a7f
KZ
619}
620
621
22853e4a
KZ
622static void
623show_tabs(void) {
624 int i, co = tigetnum("cols");
625
626 if(co > 0) {
627 printf("\r ");
628 for(i = 10; i < co-2; i+=10)
629 printf("%-10d", i);
630 putchar('\n');
631 for(i = 1; i <= co; i++)
632 putchar(i%10+'0');
633 putchar('\n');
634 for(i = 1; i < co; i++)
635 printf("\tT\b");
636 putchar('\n');
637 }
6dbe3af9
KZ
638}
639
faa0548d
SK
640static void __attribute__ ((__noreturn__))
641usage(FILE *out) {
642/* Print error message about arguments, and the command's syntax. */
643
644 if (out == stderr)
645 warnx(_("Argument error."));
646
a1e04e8f
KZ
647 fputs(_("\nUsage:\n"), out);
648 fprintf(out,
649 _(" %s [options]\n"), program_invocation_short_name);
650
651 fputs(_("\nOptions:\n"), out);
2dc87166
SK
652 fputs(_(" -term <terminal_name>\n"), out);
653 fputs(_(" -reset\n"), out);
654 fputs(_(" -initialize\n"), out);
655 fputs(_(" -cursor <on|off>\n"), out);
656 fputs(_(" -repeat <on|off>\n"), out);
657 fputs(_(" -appcursorkeys <on|off>\n"), out);
658 fputs(_(" -linewrap <on|off>\n"), out);
659 fputs(_(" -default\n"), out);
660 fputs(_(" -foreground <default|black|blue|cyan|green|magenta|red|white|yellow>\n"), out);
661 fputs(_(" -background <default|black|blue|cyan|green|magenta|red|white|yellow>\n"), out);
662 fputs(_(" -ulcolor <black|blue|bright|cyan|green|grey|magenta|red|white|yellow>\n"), out);
663 fputs(_(" -ulcolor <black|blue|bright|cyan|green|grey|magenta|red|white|yellow>\n"), out);
664 fputs(_(" -hbcolor <black|blue|bright|cyan|green|grey|magenta|red|white|yellow>\n"), out);
665 fputs(_(" -hbcolor <black|blue|bright|cyan|green|grey|magenta|red|white|yellow>\n"), out);
666 fputs(_(" -inversescreen <on|off>\n"), out);
667 fputs(_(" -bold <on|off>\n"), out);
668 fputs(_(" -half-bright <on|off>\n"), out);
669 fputs(_(" -blink <on|off>\n"), out);
670 fputs(_(" -reverse <on|off>\n"), out);
671 fputs(_(" -underline <on|off>\n"), out);
672 fputs(_(" -store\n"), out);
673 fputs(_(" -clear <all|rest>\n"), out);
674 fputs(_(" -tabs <tab1 tab2 tab3 ...> (tabn = 1-160)\n"), out);
675 fputs(_(" -clrtabs <tab1 tab2 tab3 ...> (tabn = 1-160)\n"), out);
676 fputs(_(" -regtabs <1-160>\n"), out);
677 fputs(_(" -blank <0-60|force|poke>\n"), out);
678 fputs(_(" -dump <1-NR_CONSOLES>\n"), out);
679 fputs(_(" -append <1-NR_CONSOLES>\n"), out);
680 fputs(_(" -file dumpfilename\n"), out);
681 fputs(_(" -msg <on|off>\n"), out);
682 fputs(_(" -msglevel <0-8>\n"), out);
683 fputs(_(" -powersave <on|vsync|hsync|powerdown|off>\n"), out);
684 fputs(_(" -powerdown <0-60>\n"), out);
685 fputs(_(" -blength <0-2000>\n"), out);
686 fputs(_(" -bfreq freqnumber\n"), out);
687 fputs(_(" -version\n"), out);
688 fputs(_(" -help\n"), out);
faa0548d 689
6a801e1a 690 fprintf(out, USAGE_MAN_TAIL("setterm(1)"));
faa0548d
SK
691
692 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
693}
6dbe3af9
KZ
694
695#define STRCMP(str1,str2) strncmp(str1,str2,strlen(str1))
696
22853e4a
KZ
697static void
698parse_option(char *option, int argc, char **argv, int *bad_arg) {
699 /* option: Option with leading '-' removed. */
700 /* argc: Number of arguments for this option. */
701 /* argv: Arguments for this option. */
702 /* bad_arg: Set to true if an error is detected. */
703
6dbe3af9
KZ
704/* Parse a single specification. */
705
22853e4a
KZ
706 if (STRCMP(option, "term") == 0)
707 parse_term(argc, argv, &opt_term, &opt_te_terminal_name, bad_arg);
708 else if (STRCMP(option, "reset") == 0)
709 parse_none(argc, argv, &opt_reset, bad_arg);
710 else if (STRCMP(option, "initialize") == 0)
711 parse_none(argc, argv, &opt_initialize, bad_arg);
712 else if (STRCMP(option, "cursor") == 0)
713 parse_switch(argc, argv, &opt_cursor, &opt_cu_on, bad_arg);
714 else if (STRCMP(option, "repeat") == 0)
715 parse_switch(argc, argv, &opt_repeat, &opt_rep_on, bad_arg);
716 else if (STRCMP(option, "appcursorkeys") == 0)
717 parse_switch(argc, argv, &opt_appcursorkeys, &opt_appck_on, bad_arg);
718 else if (STRCMP(option, "linewrap") == 0)
719 parse_switch(argc, argv, &opt_linewrap, &opt_li_on, bad_arg);
22853e4a
KZ
720 else if (STRCMP(option, "default") == 0)
721 parse_none(argc, argv, &opt_default, bad_arg);
722 else if (STRCMP(option, "foreground") == 0)
723 par_color(argc, argv, &opt_foreground, &opt_fo_color, bad_arg);
724 else if (STRCMP(option, "background") == 0)
725 par_color(argc, argv, &opt_background, &opt_ba_color, bad_arg);
726 else if (STRCMP(option, "ulcolor") == 0)
727 par_color2(argc, argv, &opt_ulcolor, &opt_ul_color, bad_arg);
728 else if (STRCMP(option, "hbcolor") == 0)
729 par_color2(argc, argv, &opt_hbcolor, &opt_hb_color, bad_arg);
730 else if (STRCMP(option, "inversescreen") == 0)
731 parse_switch(argc, argv, &opt_inversescreen, &opt_invsc_on, bad_arg);
732 else if (STRCMP(option, "bold") == 0)
733 parse_switch(argc, argv, &opt_bold, &opt_bo_on, bad_arg);
734 else if (STRCMP(option, "half-bright") == 0)
735 parse_switch(argc, argv, &opt_halfbright, &opt_hb_on, bad_arg);
736 else if (STRCMP(option, "blink") == 0)
737 parse_switch(argc, argv, &opt_blink, &opt_bl_on, bad_arg);
738 else if (STRCMP(option, "reverse") == 0)
739 parse_switch(argc, argv, &opt_reverse, &opt_re_on, bad_arg);
740 else if (STRCMP(option, "underline") == 0)
741 parse_switch(argc, argv, &opt_underline, &opt_un_on, bad_arg);
742 else if (STRCMP(option, "store") == 0)
743 parse_none(argc, argv, &opt_store, bad_arg);
744 else if (STRCMP(option, "clear") == 0)
745 parse_clear(argc, argv, &opt_clear, &opt_cl_all, bad_arg);
746 else if (STRCMP(option, "tabs") == 0)
747 parse_tabs(argc, argv, &opt_tabs, opt_tb_array, bad_arg);
748 else if (STRCMP(option, "clrtabs") == 0)
749 parse_clrtabs(argc, argv, &opt_clrtabs, opt_tb_array, bad_arg);
750 else if (STRCMP(option, "regtabs") == 0)
751 parse_regtabs(argc, argv, &opt_regtabs, &opt_rt_len, bad_arg);
752 else if (STRCMP(option, "blank") == 0)
753 parse_blank(argc, argv, &opt_blank, &opt_bl_min, bad_arg);
754 else if (STRCMP(option, "dump") == 0)
755 parse_snap(argc, argv, &opt_snap, &opt_sn_num, bad_arg);
756 else if (STRCMP(option, "append") == 0)
757 parse_snap(argc, argv, &opt_append, &opt_sn_num, bad_arg);
758 else if (STRCMP(option, "file") == 0)
759 parse_snapfile(argc, argv, &opt_snapfile, (int *)opt_sn_name, bad_arg);
760 else if (STRCMP(option, "msg") == 0)
761 parse_switch(argc, argv, &opt_msg, &opt_msg_on, bad_arg);
762 else if (STRCMP(option, "msglevel") == 0)
763 parse_msglevel(argc, argv, &opt_msglevel, &opt_msglevel_num, bad_arg);
764 else if (STRCMP(option, "powersave") == 0)
765 parse_powersave(argc, argv, &opt_powersave, &opt_ps_mode, bad_arg);
766 else if (STRCMP(option, "powerdown") == 0)
767 parse_blank(argc, argv, &opt_powerdown, &opt_pd_min, bad_arg);
768 else if (STRCMP(option, "blength") == 0)
769 parse_blength(argc, argv, &opt_blength, &opt_blength_l, bad_arg);
770 else if (STRCMP(option, "bfreq") == 0)
771 parse_bfreq(argc, argv, &opt_bfreq, &opt_bfreq_f, bad_arg);
faa0548d
SK
772 else if (STRCMP(option, "version") == 0) {
773 printf(_("%s from %s\n"), program_invocation_short_name,
774 PACKAGE_STRING);
775 exit(EXIT_SUCCESS);
776 } else if (STRCMP(option, "help") == 0)
777 usage(stdout);
22853e4a
KZ
778 else
779 *bad_arg = TRUE;
6dbe3af9
KZ
780}
781
782/* End of command line parsing routines. */
783
22853e4a
KZ
784static char *ti_entry(const char *name) {
785 /* name: Terminfo capability string to lookup. */
786
fd6b7a7f 787/* Return the specified terminfo string, or an empty string if no such terminfo
6dbe3af9
KZ
788 * capability exists.
789 */
790
22853e4a 791 char *buf_ptr;
6dbe3af9 792
ffc43748
KZ
793 if ((buf_ptr = tigetstr((char *)name)) == (char *)-1)
794 buf_ptr = NULL;
22853e4a 795 return buf_ptr;
6dbe3af9
KZ
796}
797
22853e4a
KZ
798static void
799perform_sequence(int vcterm) {
800 /* vcterm: Set if terminal is a virtual console. */
801
802 int result;
6dbe3af9
KZ
803/* Perform the selected options. */
804
22853e4a
KZ
805 /* -reset. */
806 if (opt_reset) {
807 putp(ti_entry("rs1"));
808 }
6dbe3af9 809
22853e4a
KZ
810 /* -initialize. */
811 if (opt_initialize) {
812 putp(ti_entry("is2"));
813 }
6dbe3af9 814
22853e4a
KZ
815 /* -cursor [on|off]. */
816 if (opt_cursor) {
817 if (opt_cu_on)
818 putp(ti_entry("cnorm"));
819 else
820 putp(ti_entry("civis"));
821 }
6dbe3af9 822
22853e4a 823 /* -linewrap [on|off]. Vc only (vt102) */
6ed37604
KZ
824 if (opt_linewrap && vcterm)
825 fputs(opt_li_on ? "\033[?7h" : "\033[?7l", stdout);
6dbe3af9 826
22853e4a 827 /* -repeat [on|off]. Vc only (vt102) */
6ed37604
KZ
828 if (opt_repeat && vcterm)
829 fputs(opt_rep_on ? "\033[?8h" : "\033[?8l", stdout);
6dbe3af9 830
22853e4a 831 /* -appcursorkeys [on|off]. Vc only (vt102) */
6ed37604
KZ
832 if (opt_appcursorkeys && vcterm)
833 fputs(opt_appck_on ? "\033[?1h" : "\033[?1l", stdout);
6dbe3af9 834
22853e4a
KZ
835 /* -default. Vc sets default rendition, otherwise clears all
836 * attributes.
837 */
838 if (opt_default) {
6dbe3af9 839 if (vcterm)
22853e4a 840 printf("\033[0m");
6dbe3af9 841 else
fd6b7a7f 842 putp(ti_entry("sgr0"));
6dbe3af9 843 }
22853e4a
KZ
844
845 /* -foreground black|red|green|yellow|blue|magenta|cyan|white|default.
846 * Vc only (ANSI).
847 */
6ed37604
KZ
848 if (opt_foreground && vcterm)
849 printf("\033[3%c%s", '0' + opt_fo_color, "m");
22853e4a
KZ
850
851 /* -background black|red|green|yellow|blue|magenta|cyan|white|default.
852 * Vc only (ANSI).
853 */
6ed37604
KZ
854 if (opt_background && vcterm)
855 printf("\033[4%c%s", '0' + opt_ba_color, "m");
22853e4a
KZ
856
857 /* -ulcolor black|red|green|yellow|blue|magenta|cyan|white|default.
858 * Vc only.
859 */
860 if (opt_ulcolor && vcterm) {
861 printf("\033[1;%d]", opt_ul_color);
862 }
863
864 /* -hbcolor black|red|green|yellow|blue|magenta|cyan|white|default.
865 * Vc only.
866 */
867 if (opt_hbcolor && vcterm) {
868 printf("\033[2;%d]", opt_hb_color);
869 }
870
871 /* -inversescreen [on|off]. Vc only (vt102).
872 */
6ed37604
KZ
873 if (opt_inversescreen && vcterm)
874 fputs(opt_invsc_on ? "\033[?5h" : "\033[?5l", stdout);
22853e4a
KZ
875
876 /* -bold [on|off]. Vc behaves as expected, otherwise off turns off
877 * all attributes.
878 */
879 if (opt_bold) {
880 if (opt_bo_on)
881 putp(ti_entry("bold"));
882 else {
883 if (vcterm)
6ed37604 884 fputs("\033[22m", stdout);
22853e4a
KZ
885 else
886 putp(ti_entry("sgr0"));
887 }
888 }
889
890 /* -half-bright [on|off]. Vc behaves as expected, otherwise off turns off
891 * all attributes.
892 */
893 if (opt_halfbright) {
894 if (opt_hb_on)
895 putp(ti_entry("dim"));
896 else {
897 if (vcterm)
6ed37604 898 fputs("\033[22m", stdout);
22853e4a
KZ
899 else
900 putp(ti_entry("sgr0"));
901 }
902 }
903
904 /* -blink [on|off]. Vc behaves as expected, otherwise off turns off
905 * all attributes.
906 */
907 if (opt_blink) {
908 if (opt_bl_on)
909 putp(ti_entry("blink"));
910 else {
911 if (vcterm)
6ed37604 912 fputs("\033[25m", stdout);
22853e4a
KZ
913 else
914 putp(ti_entry("sgr0"));
915 }
916 }
917
918 /* -reverse [on|off]. Vc behaves as expected, otherwise off turns
919 * off all attributes.
920 */
921 if (opt_reverse) {
922 if (opt_re_on)
923 putp(ti_entry("rev"));
924 else {
925 if (vcterm)
6ed37604 926 fputs("\033[27m", stdout);
22853e4a
KZ
927 else
928 putp(ti_entry("sgr0"));
929 }
930 }
931
932 /* -underline [on|off]. */
6ed37604
KZ
933 if (opt_underline)
934 putp(ti_entry(opt_un_on ? "smul" : "rmul"));
22853e4a
KZ
935
936 /* -store. Vc only. */
6ed37604
KZ
937 if (opt_store && vcterm)
938 fputs("\033[8]", stdout);
22853e4a
KZ
939
940 /* -clear [all|rest]. */
6ed37604
KZ
941 if (opt_clear)
942 putp(ti_entry(opt_cl_all ? "clear" : "ed"));
22853e4a
KZ
943
944 /* -tabs Vc only. */
945 if (opt_tabs && vcterm) {
946 int i;
947
948 if (opt_tb_array[0] == -1)
949 show_tabs();
950 else {
951 for(i=0; opt_tb_array[i] > 0; i++)
952 printf("\033[%dG\033H", opt_tb_array[i]);
953 putchar('\r');
954 }
955 }
956
957 /* -clrtabs Vc only. */
958 if (opt_clrtabs && vcterm) {
959 int i;
960
961 if (opt_tb_array[0] == -1)
6ed37604 962 fputs("\033[3g", stdout);
6dbe3af9 963 else
22853e4a
KZ
964 for(i=0; opt_tb_array[i] > 0; i++)
965 printf("\033[%dG\033[g", opt_tb_array[i]);
966 putchar('\r');
6dbe3af9 967 }
6dbe3af9 968
22853e4a
KZ
969 /* -regtabs Vc only. */
970 if (opt_regtabs && vcterm) {
971 int i;
972
6ed37604 973 fputs("\033[3g\r", stdout);
22853e4a
KZ
974 for(i=opt_rt_len+1; i<=160; i+=opt_rt_len)
975 printf("\033[%dC\033H",opt_rt_len);
976 putchar('\r');
977 }
978
979 /* -blank [0-60]. */
5c55d9bf
ST
980 if (opt_blank && vcterm) {
981 if (opt_bl_min >= 0)
982 printf("\033[9;%d]", opt_bl_min);
983 else if (opt_bl_min == BLANKSCREEN) {
984 char ioctlarg = TIOCL_BLANKSCREEN;
985 if (ioctl(0,TIOCLINUX,&ioctlarg))
261f1423 986 warn(_("cannot force blank"));
5c55d9bf
ST
987 } else if (opt_bl_min == UNBLANKSCREEN) {
988 char ioctlarg = TIOCL_UNBLANKSCREEN;
989 if (ioctl(0,TIOCLINUX,&ioctlarg))
261f1423 990 warn(_("cannot force unblank"));
5c55d9bf
ST
991 } else if (opt_bl_min == BLANKEDSCREEN) {
992 char ioctlarg = TIOCL_BLANKEDSCREEN;
993 int ret;
994 ret = ioctl(0,TIOCLINUX,&ioctlarg);
995 if (ret < 0)
261f1423 996 warn(_("cannot get blank status"));
5c55d9bf
ST
997 else
998 printf("%d\n",ret);
999 }
1000 }
1001
22853e4a
KZ
1002 /* -powersave [on|vsync|hsync|powerdown|off] (console) */
1003 if (opt_powersave) {
1004 char ioctlarg[2];
5c55d9bf 1005 ioctlarg[0] = TIOCL_SETVESABLANK;
22853e4a
KZ
1006 ioctlarg[1] = opt_ps_mode;
1007 if (ioctl(0,TIOCLINUX,ioctlarg))
261f1423 1008 warn(_("cannot (un)set powersave mode"));
22853e4a
KZ
1009 }
1010
1011 /* -powerdown [0-60]. */
1012 if (opt_powerdown) {
1013 printf("\033[14;%d]", opt_pd_min);
1014 }
fd6b7a7f 1015
22853e4a
KZ
1016 /* -snap [1-NR_CONS]. */
1017 if (opt_snap || opt_append) {
1018 FILE *F;
1019
1020 F = fopen(opt_sn_name, opt_snap ? "w" : "a");
261f1423
SK
1021 if (!F)
1022 err(EXIT_DUMPFILE, _("can not open dump file %s for output"),
22853e4a 1023 opt_sn_name);
22853e4a 1024 screendump(opt_sn_num, F);
cdd2a8c3
SK
1025 if (close_stream(F) != 0)
1026 errx(EXIT_FAILURE, _("write error"));
22853e4a
KZ
1027 }
1028
1029 /* -msg [on|off]. */
1030 if (opt_msg && vcterm) {
1031 if (opt_msg_on)
1032 /* 7 -- Enable printk's to console */
1033 result = klogctl(7, NULL, 0);
1034 else
1035 /* 6 -- Disable printk's to console */
1036 result = klogctl(6, NULL, 0);
1037
1038 if (result != 0)
261f1423 1039 warn(_("klogctl error"));
22853e4a
KZ
1040 }
1041
1042 /* -msglevel [0-8] */
1043 if (opt_msglevel && vcterm) {
1044 /* 8 -- Set level of messages printed to console */
1045 result = klogctl(8, NULL, opt_msglevel_num);
1046 if (result != 0)
261f1423 1047 warn(_("klogctl error"));
22853e4a
KZ
1048 }
1049
1050 /* -blength [0-2000] */
1051 if (opt_blength && vcterm) {
1052 printf("\033[11;%d]", opt_blength_l);
1053 }
b6e899d9 1054
22853e4a
KZ
1055 /* -bfreq freqnumber */
1056 if (opt_bfreq && vcterm) {
1057 printf("\033[10;%d]", opt_bfreq_f);
1058 }
fd6b7a7f 1059
6dbe3af9
KZ
1060}
1061
22853e4a 1062static void
a973947c
SK
1063screendump(int vcnum, FILE * F)
1064{
1065 char infile[MAXPATHLEN];
1066 unsigned char header[4];
1067 unsigned int rows, cols;
172ba4f2
SK
1068 int fd;
1069 size_t i, j;
747c1d9d 1070 ssize_t rc;
a77e7ac7 1071 char *inbuf = NULL, *outbuf = NULL, *p, *q;
a973947c 1072
a5a16c68 1073 sprintf(infile, "/dev/vcsa%d", vcnum);
a973947c
SK
1074 fd = open(infile, O_RDONLY);
1075 if (fd < 0 && vcnum == 0) {
1076 /* vcsa0 is often called vcsa */
1077 sprintf(infile, "/dev/vcsa");
1078 fd = open(infile, O_RDONLY);
1079 }
1080 if (fd < 0) {
1081 /* try devfs name - for zero vcnum just /dev/vcc/a */
1082 /* some gcc's warn for %.u - add 0 */
1083 sprintf(infile, "/dev/vcc/a%.0u", vcnum);
1084 fd = open(infile, O_RDONLY);
1085 }
1086 if (fd < 0) {
1087 sprintf(infile, "/dev/vcsa%d", vcnum);
1088 goto read_error;
1089 }
1090 if (read(fd, header, 4) != 4)
1091 goto read_error;
1092 rows = header[0];
1093 cols = header[1];
1094 if (rows * cols == 0)
1095 goto read_error;
9497ebb0
KZ
1096
1097 inbuf = xmalloc(rows * cols * 2);
1098 outbuf = xmalloc(rows * (cols + 1));
1099
747c1d9d
KZ
1100 rc = read(fd, inbuf, rows * cols * 2);
1101 if (rc < 0 || (size_t) rc != rows * cols * 2)
a973947c
SK
1102 goto read_error;
1103 p = inbuf;
1104 q = outbuf;
1105 for (i = 0; i < rows; i++) {
1106 for (j = 0; j < cols; j++) {
1107 *q++ = *p;
1108 p += 2;
1109 }
1110 while (j-- > 0 && q[-1] == ' ')
1111 q--;
1112 *q++ = '\n';
1113 }
172ba4f2 1114 if (fwrite(outbuf, 1, q - outbuf, F) != (size_t) (q - outbuf)) {
a973947c
SK
1115 warnx(_("Error writing screendump"));
1116 goto error;
6dbe3af9 1117 }
a973947c 1118 close(fd);
a77e7ac7
KZ
1119 free(inbuf);
1120 free(outbuf);
a973947c
SK
1121 return;
1122
2754ffc5
PU
1123read_error:
1124 if (vcnum != 0)
1125 warnx(_("Couldn't read %s"), infile);
1126 else
1127 warnx(_("Couldn't read neither /dev/vcsa0 nor /dev/vcsa"));
1128
1129error:
a973947c
SK
1130 if (fd >= 0)
1131 close(fd);
a77e7ac7
KZ
1132 free(inbuf);
1133 free(outbuf);
a973947c 1134 exit(EXIT_FAILURE);
6dbe3af9
KZ
1135}
1136
22853e4a
KZ
1137int
1138main(int argc, char **argv) {
1139 int bad_arg = FALSE; /* Set if error in arguments. */
1140 int arg, modifier;
1141 char *term; /* Terminal type. */
1142 int vcterm; /* Set if terminal is a virtual console. */
261f1423 1143 int errret;
6dbe3af9 1144
22853e4a
KZ
1145 setlocale(LC_ALL, "");
1146 bindtextdomain(PACKAGE, LOCALEDIR);
1147 textdomain(PACKAGE);
cdd2a8c3 1148 atexit(close_stdout);
b6e899d9 1149
22853e4a
KZ
1150 if (argc < 2)
1151 bad_arg = TRUE;
6dbe3af9 1152
22853e4a 1153 /* Parse arguments. */
6dbe3af9 1154
22853e4a
KZ
1155 for (arg = 1; arg < argc;) {
1156 if (*argv[arg] == '-') {
6dbe3af9 1157
22853e4a 1158 /* Parse a single option. */
6dbe3af9 1159
22853e4a
KZ
1160 for (modifier = arg + 1; modifier < argc; modifier++) {
1161 if (*argv[modifier] == '-') break;
1162 }
1163 parse_option(argv[arg] + 1, modifier - arg - 1,
1164 &argv[arg + 1], &bad_arg);
1165 arg = modifier;
1166 } else {
1167 bad_arg = TRUE;
1168 arg++;
6dbe3af9 1169 }
6dbe3af9 1170 }
6dbe3af9 1171
22853e4a 1172 /* Display syntax message if error in arguments. */
6dbe3af9 1173
faa0548d
SK
1174 if (bad_arg)
1175 usage(stderr);
6dbe3af9 1176
22853e4a 1177 /* Find out terminal name. */
6dbe3af9 1178
22853e4a
KZ
1179 if (opt_term) {
1180 term = opt_te_terminal_name;
1181 } else {
1182 term = getenv("TERM");
261f1423
SK
1183 if (term == NULL)
1184 errx(EXIT_FAILURE, _("$TERM is not defined."));
6dbe3af9 1185 }
6dbe3af9 1186
22853e4a 1187 /* Find terminfo entry. */
6dbe3af9 1188
261f1423
SK
1189 if (setupterm(term, 1, &errret))
1190 switch(errret) {
1191 case -1:
1192 errx(EXIT_FAILURE, _("terminfo database cannot be found"));
1193 case 0:
1194 errx(EXIT_FAILURE, _("%s: unknown terminal type"), term);
1195 case 1:
1196 errx(EXIT_FAILURE, _("terminal is hardcopy"));
1197 }
6dbe3af9 1198
22853e4a 1199 /* See if the terminal is a virtual console terminal. */
6dbe3af9 1200
22853e4a 1201 vcterm = (!strncmp(term, "con", 3) || !strncmp(term, "linux", 5));
6dbe3af9 1202
22853e4a 1203 /* Perform the selected options. */
6dbe3af9 1204
22853e4a 1205 perform_sequence(vcterm);
6dbe3af9 1206
261f1423 1207 return EXIT_SUCCESS;
6dbe3af9 1208}