]>
Commit | Line | Data |
---|---|---|
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 | 136 | extern 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 |
144 | enum { |
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 |
158 | enum { |
159 | BLANKSCREEN = -1, | |
160 | UNBLANKSCREEN = -2, | |
161 | BLANKEDSCREEN = -3 | |
162 | }; | |
5c55d9bf ST |
163 | |
164 | /* <linux/tiocl.h> fallback */ | |
165 | #ifndef TIOCL_BLANKSCREEN | |
010f219d SK |
166 | enum { |
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 | 175 | int opt_term, opt_reset, opt_initialize, opt_cursor; |
45656c9f | 176 | int opt_linewrap, opt_default, opt_foreground; |
6dbe3af9 | 177 | int opt_background, opt_bold, opt_blink, opt_reverse, opt_underline; |
45656c9f | 178 | int opt_store, opt_clear, opt_blank, opt_snap, opt_snapfile; |
6dbe3af9 KZ |
179 | int opt_append, opt_ulcolor, opt_hbcolor, opt_halfbright, opt_repeat; |
180 | int opt_tabs, opt_clrtabs, opt_regtabs, opt_appcursorkeys, opt_inversescreen; | |
fd6b7a7f KZ |
181 | int opt_msg, opt_msglevel, opt_powersave, opt_powerdown; |
182 | int opt_blength, opt_bfreq; | |
6dbe3af9 KZ |
183 | |
184 | /* Option controls. The variable names have been contracted to ensure | |
185 | * uniqueness. | |
186 | */ | |
187 | char *opt_te_terminal_name; /* Terminal name. */ | |
45656c9f | 188 | int opt_cu_on, opt_li_on, opt_bo_on, opt_hb_on, opt_bl_on; |
6dbe3af9 | 189 | int opt_re_on, opt_un_on, opt_rep_on, opt_appck_on, opt_invsc_on; |
fd6b7a7f | 190 | int opt_msg_on; /* Boolean switches. */ |
6dbe3af9 KZ |
191 | int opt_fo_color, opt_ba_color; /* Colors. */ |
192 | int opt_ul_color, opt_hb_color; | |
193 | int opt_cl_all; /* Clear all or rest. */ | |
194 | int opt_bl_min; /* Blank screen. */ | |
fd6b7a7f KZ |
195 | int opt_blength_l; |
196 | int opt_bfreq_f; | |
a5a16c68 | 197 | int opt_sn_num; /* Snap screen. */ |
6dbe3af9 KZ |
198 | int opt_rt_len; /* regular tab length */ |
199 | int opt_tb_array[161]; /* Array for tab list */ | |
200 | int opt_msglevel_num; | |
fd6b7a7f | 201 | int opt_ps_mode, opt_pd_min; /* powersave mode/powerdown time */ |
6dbe3af9 | 202 | |
29715436 | 203 | char opt_sn_name[PATH_MAX + 1] = "screen.dump"; |
6dbe3af9 | 204 | |
22853e4a | 205 | static 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 | 212 | static void |
4d9e37bf | 213 | parse_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 | 229 | static void |
172ba4f2 | 230 | parse_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 |
243 | static void |
244 | parse_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 |
268 | static void |
269 | par_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 |
310 | static void |
311 | par_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 |
366 | static void |
367 | parse_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 |
391 | static void |
392 | parse_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 |
419 | static void |
420 | parse_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 |
450 | static void |
451 | parse_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 |
470 | static void |
471 | parse_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 |
492 | static void |
493 | parse_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 |
510 | static void |
511 | parse_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 |
531 | static void |
532 | parse_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 |
556 | static void |
557 | parse_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 |
579 | static void |
580 | parse_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 |
601 | static void |
602 | parse_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 |
622 | static void |
623 | show_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 |
640 | static void __attribute__ ((__noreturn__)) |
641 | usage(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 |
697 | static void |
698 | parse_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 |
784 | static 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 |
798 | static void |
799 | perform_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 | 1062 | static void |
a973947c SK |
1063 | screendump(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 |
1123 | read_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 | ||
1129 | error: | |
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 |
1137 | int |
1138 | main(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 | } |