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