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