2006-12-06 17:25:32 -06:00
|
|
|
/* setterm.c, set terminal attributes.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1990 Gordon Irlam (gordoni@cs.ua.oz.au). Conditions of use,
|
|
|
|
* modification, and redistribution are contained in the file COPYRIGHT that
|
|
|
|
* forms part of this distribution.
|
2019-08-28 18:25:57 -05:00
|
|
|
*
|
2006-12-06 17:25:32 -06:00
|
|
|
* Adaption to Linux by Peter MacDonald.
|
|
|
|
*
|
|
|
|
* Enhancements by Mika Liljeberg (liljeber@cs.Helsinki.FI)
|
|
|
|
*
|
2006-12-06 17:25:34 -06:00
|
|
|
* Beep modifications by Christophe Jolif (cjolif@storm.gatelink.fr.net)
|
|
|
|
*
|
|
|
|
* Sanity increases by Cafeine Addict [sic].
|
|
|
|
*
|
2006-12-06 17:25:41 -06:00
|
|
|
* Powersave features by todd j. derr <tjd@wordsmith.org>
|
2006-12-06 17:25:34 -06:00
|
|
|
*
|
|
|
|
* Converted to terminfo by Kars de Jong (jongk@cs.utwente.nl)
|
2006-12-06 17:25:32 -06:00
|
|
|
*
|
2013-01-26 10:07:51 -06:00
|
|
|
* 1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
|
2006-12-06 17:25:39 -06:00
|
|
|
* - added Native Language Support
|
|
|
|
*
|
2006-12-06 17:25:32 -06:00
|
|
|
* Semantics:
|
|
|
|
*
|
2006-12-06 17:25:34 -06:00
|
|
|
* Setterm writes to standard output a character string that will
|
2012-05-29 12:06:50 -05:00
|
|
|
* invoke the specified terminal capabilities. Where possible
|
2006-12-06 17:25:34 -06:00
|
|
|
* terminfo is consulted to find the string to use. Some options
|
|
|
|
* however do not correspond to a terminfo capability. In this case if
|
|
|
|
* the terminal type is "con*", or "linux*" the string that invokes
|
|
|
|
* the specified capabilities on the PC Linux virtual console driver
|
|
|
|
* is output. Options that are not implemented by the terminal are
|
|
|
|
* ignored.
|
2006-12-06 17:25:32 -06:00
|
|
|
*
|
|
|
|
* The following options are non-obvious.
|
|
|
|
*
|
|
|
|
* -term can be used to override the TERM environment variable.
|
|
|
|
*
|
|
|
|
* -reset displays the terminal reset string, which typically resets the
|
|
|
|
* terminal to its power on state.
|
|
|
|
*
|
|
|
|
* -initialize displays the terminal initialization string, which typically
|
|
|
|
* sets the terminal's rendering options, and other attributes to the
|
|
|
|
* default values.
|
|
|
|
*
|
|
|
|
* -default sets the terminal's rendering options to the default values.
|
|
|
|
*
|
|
|
|
* -store stores the terminal's current rendering options as the default
|
2006-12-06 17:25:34 -06:00
|
|
|
* values. */
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-11 16:52:09 -05:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2014-05-17 12:52:01 -05:00
|
|
|
#include <getopt.h>
|
2006-12-06 17:25:32 -06:00
|
|
|
#include <stdio.h>
|
2006-12-06 17:25:43 -06:00
|
|
|
#include <stdlib.h>
|
2006-12-06 17:25:32 -06:00
|
|
|
#include <string.h>
|
2014-05-11 16:52:09 -05:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/klog.h>
|
|
|
|
#include <sys/param.h> /* for MAXPATHLEN */
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <unistd.h>
|
2013-09-28 23:44:36 -05:00
|
|
|
|
2017-05-31 04:01:46 -05:00
|
|
|
#if defined(HAVE_NCURSESW_TERM_H)
|
|
|
|
# include <ncursesw/term.h>
|
2017-05-30 10:15:37 -05:00
|
|
|
#elif defined(HAVE_NCURSES_TERM_H)
|
|
|
|
# include <ncurses/term.h>
|
2017-05-31 04:01:46 -05:00
|
|
|
#elif defined(HAVE_TERM_H)
|
|
|
|
# include <term.h>
|
2006-12-06 17:25:37 -06:00
|
|
|
#endif
|
2006-12-06 17:26:54 -06:00
|
|
|
|
2007-11-27 16:54:35 -06:00
|
|
|
#ifdef HAVE_LINUX_TIOCL_H
|
2014-05-11 16:52:09 -05:00
|
|
|
# include <linux/tiocl.h>
|
2007-11-27 16:54:35 -06:00
|
|
|
#endif
|
2009-10-15 18:40:58 -05:00
|
|
|
|
2016-12-29 04:28:54 -06:00
|
|
|
#include "all-io.h"
|
2009-10-15 18:40:58 -05:00
|
|
|
#include "c.h"
|
2012-04-04 12:44:04 -05:00
|
|
|
#include "closestream.h"
|
2014-05-11 16:52:09 -05:00
|
|
|
#include "nls.h"
|
2014-05-18 08:39:58 -05:00
|
|
|
#include "optutils.h"
|
2014-05-17 13:21:34 -05:00
|
|
|
#include "strutils.h"
|
2014-05-11 16:52:09 -05:00
|
|
|
#include "xalloc.h"
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:34 -06:00
|
|
|
/* Constants. */
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2011-04-02 15:56:52 -05:00
|
|
|
/* Non-standard return values. */
|
|
|
|
#define EXIT_DUMPFILE -1
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
/* Colors. */
|
2014-05-11 14:26:48 -05:00
|
|
|
enum {
|
|
|
|
BLACK = 0,
|
|
|
|
RED,
|
|
|
|
GREEN,
|
|
|
|
YELLOW,
|
|
|
|
BLUE,
|
|
|
|
MAGENTA,
|
|
|
|
CYAN,
|
|
|
|
WHITE,
|
|
|
|
GREY,
|
|
|
|
DEFAULT
|
|
|
|
};
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2016-05-09 05:35:41 -05:00
|
|
|
static const char *colornames[] = {
|
|
|
|
[BLACK] = "black",
|
|
|
|
[RED] = "red",
|
|
|
|
[GREEN] = "green",
|
|
|
|
[YELLOW]= "yellow",
|
|
|
|
[BLUE] = "blue",
|
|
|
|
[MAGENTA]="magenta",
|
|
|
|
[CYAN] = "cyan",
|
|
|
|
[WHITE] = "white",
|
|
|
|
[GREY] = "grey",
|
|
|
|
[DEFAULT] = "default"
|
|
|
|
};
|
|
|
|
|
|
|
|
#define is_valid_color(x) (x >= 0 && (size_t) x < ARRAY_SIZE(colornames))
|
|
|
|
|
2007-11-27 16:54:35 -06:00
|
|
|
/* Blank commands */
|
2014-05-11 14:26:48 -05:00
|
|
|
enum {
|
|
|
|
BLANKSCREEN = -1,
|
|
|
|
UNBLANKSCREEN = -2,
|
|
|
|
BLANKEDSCREEN = -3
|
|
|
|
};
|
2007-11-27 16:54:35 -06:00
|
|
|
|
|
|
|
/* <linux/tiocl.h> fallback */
|
|
|
|
#ifndef TIOCL_BLANKSCREEN
|
2014-05-11 14:26:48 -05:00
|
|
|
enum {
|
|
|
|
TIOCL_UNBLANKSCREEN = 4, /* unblank screen */
|
|
|
|
TIOCL_SETVESABLANK = 10, /* set vesa blanking mode */
|
|
|
|
TIOCL_BLANKSCREEN = 14, /* keep screen blank even if a key is pressed */
|
|
|
|
TIOCL_BLANKEDSCREEN = 15 /* return which vt was blanked */
|
|
|
|
};
|
2007-11-27 16:54:35 -06:00
|
|
|
#endif
|
|
|
|
|
2014-05-11 14:26:49 -05:00
|
|
|
/* Powersave modes */
|
|
|
|
enum {
|
|
|
|
VESA_BLANK_MODE_OFF = 0,
|
|
|
|
VESA_BLANK_MODE_SUSPENDV,
|
|
|
|
VESA_BLANK_MODE_SUSPENDH,
|
|
|
|
VESA_BLANK_MODE_POWERDOWN
|
|
|
|
};
|
|
|
|
|
|
|
|
/* klogctl() actions */
|
|
|
|
enum {
|
|
|
|
SYSLOG_ACTION_CONSOLE_OFF = 6,
|
|
|
|
SYSLOG_ACTION_CONSOLE_ON = 7,
|
|
|
|
SYSLOG_ACTION_CONSOLE_LEVEL = 8
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Console log levels */
|
|
|
|
enum {
|
2014-05-18 06:31:16 -05:00
|
|
|
CONSOLE_LEVEL_MIN = 0,
|
2014-05-11 14:26:49 -05:00
|
|
|
CONSOLE_LEVEL_MAX = 8
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Various numbers */
|
|
|
|
#define DEFAULT_TAB_LEN 8
|
|
|
|
#define BLANK_MAX 60
|
|
|
|
#define TABS_MAX 160
|
|
|
|
#define BLENGTH_MAX 2000
|
|
|
|
|
2014-05-18 05:00:14 -05:00
|
|
|
/* Command controls. */
|
2014-05-18 03:35:01 -05:00
|
|
|
struct setterm_control {
|
|
|
|
char *opt_te_terminal_name; /* terminal name */
|
|
|
|
int opt_bl_min; /* blank screen */
|
|
|
|
int opt_blength_l; /* bell duration in milliseconds */
|
|
|
|
int opt_bfreq_f; /* bell frequency in Hz */
|
2016-05-29 16:11:53 -05:00
|
|
|
int opt_sn_num; /* console number to be snapshot */
|
2014-05-18 03:35:01 -05:00
|
|
|
char *opt_sn_name; /* path to write snap */
|
2014-05-18 05:00:14 -05:00
|
|
|
char *in_device; /* device to snapshot */
|
2016-05-29 16:11:53 -05:00
|
|
|
int opt_msglevel_num; /* printk() logging level */
|
2014-05-18 03:35:01 -05:00
|
|
|
int opt_ps_mode; /* powersave mode */
|
|
|
|
int opt_pd_min; /* powerdown time */
|
|
|
|
int opt_rt_len; /* regular tab length */
|
|
|
|
int opt_tb_array[TABS_MAX + 1]; /* array for tab list */
|
|
|
|
/* colors */
|
2017-02-25 11:35:17 -06:00
|
|
|
unsigned int opt_fo_color:4, opt_ba_color:4, opt_ul_color:4, opt_hb_color:4;
|
2014-05-18 03:35:01 -05:00
|
|
|
/* boolean options */
|
2014-10-15 16:19:26 -05:00
|
|
|
unsigned int opt_cu_on:1, opt_li_on:1, opt_bo_on:1, opt_hb_on:1,
|
|
|
|
opt_bl_on:1, opt_re_on:1, opt_un_on:1, opt_rep_on:1,
|
|
|
|
opt_appck_on:1, opt_invsc_on:1, opt_msg_on:1, opt_cl_all:1,
|
|
|
|
vcterm:1;
|
2014-05-18 03:35:01 -05:00
|
|
|
/* Option flags. Set when an option is invoked. */
|
2016-12-29 04:28:54 -06:00
|
|
|
uint64_t opt_term:1, opt_reset:1, opt_resize:1, opt_initialize:1, opt_cursor:1,
|
2014-05-18 03:35:01 -05:00
|
|
|
opt_linewrap:1, opt_default:1, opt_foreground:1,
|
|
|
|
opt_background:1, opt_bold:1, opt_blink:1, opt_reverse:1,
|
|
|
|
opt_underline:1, opt_store:1, opt_clear:1, opt_blank:1,
|
|
|
|
opt_snap:1, opt_snapfile:1, opt_append:1, opt_ulcolor:1,
|
|
|
|
opt_hbcolor:1, opt_halfbright:1, opt_repeat:1, opt_tabs:1,
|
|
|
|
opt_clrtabs:1, opt_regtabs:1, opt_appcursorkeys:1,
|
|
|
|
opt_inversescreen:1, opt_msg:1, opt_msglevel:1, opt_powersave:1,
|
|
|
|
opt_powerdown:1, opt_blength:1, opt_bfreq:1;
|
|
|
|
};
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2016-05-09 05:35:41 -05:00
|
|
|
static int parse_color(const char *arg)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(colornames); i++) {
|
|
|
|
if (strcmp(colornames[i], arg) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2014-05-17 12:52:01 -05:00
|
|
|
static int parse_febg_color(const char *arg)
|
|
|
|
{
|
2016-05-09 05:35:41 -05:00
|
|
|
int color = parse_color(arg);
|
2014-05-17 13:21:34 -05:00
|
|
|
|
2016-05-09 05:35:41 -05:00
|
|
|
if (color < 0)
|
2014-05-17 13:21:34 -05:00
|
|
|
color = strtos32_or_err(arg, _("argument error"));
|
2016-05-09 05:35:41 -05:00
|
|
|
|
|
|
|
if (!is_valid_color(color) || color == GREY)
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
2014-05-17 13:21:34 -05:00
|
|
|
return color;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static int parse_ulhb_color(char **av, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
char *color_name;
|
|
|
|
int bright = 0;
|
|
|
|
int color = -1;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
if (av[*oi] && strcmp(av[*oi - 1], "bright") == 0) {
|
2014-05-17 12:52:01 -05:00
|
|
|
bright = 1;
|
2016-07-03 07:13:21 -05:00
|
|
|
color_name = av[*oi];
|
|
|
|
(*oi)++;
|
2014-05-17 12:52:01 -05:00
|
|
|
} else
|
2016-07-03 07:13:21 -05:00
|
|
|
color_name = av[*oi - 1];
|
2014-05-17 12:52:01 -05:00
|
|
|
|
2016-05-09 05:35:41 -05:00
|
|
|
color = parse_color(color_name);
|
|
|
|
if (color < 0)
|
2014-05-17 13:21:34 -05:00
|
|
|
color = strtos32_or_err(color_name, _("argument error"));
|
2019-03-07 14:42:09 -06:00
|
|
|
if (!is_valid_color(color) || color == DEFAULT)
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), color_name);
|
2014-05-17 12:52:01 -05:00
|
|
|
if (bright && (color == BLACK || color == GREY))
|
|
|
|
errx(EXIT_FAILURE, _("argument error: bright %s is not supported"), color_name);
|
|
|
|
|
2019-03-07 14:55:07 -06:00
|
|
|
if (bright)
|
|
|
|
color |= 8;
|
|
|
|
|
2014-05-17 12:52:01 -05:00
|
|
|
return color;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static char *find_optional_arg(char **av, char *oa, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
char *arg;
|
2016-07-03 07:13:21 -05:00
|
|
|
if (oa)
|
|
|
|
return oa;
|
2020-04-19 00:16:22 -05:00
|
|
|
|
|
|
|
arg = av[*oi];
|
|
|
|
if (!arg || arg[0] == '-')
|
|
|
|
return NULL;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
(*oi)++;
|
2014-05-17 12:52:01 -05:00
|
|
|
return arg;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static int parse_blank(char **av, char *oa, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
char *arg;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
arg = find_optional_arg(av, oa, oi);
|
2014-05-17 12:52:01 -05:00
|
|
|
if (!arg)
|
|
|
|
return BLANKEDSCREEN;
|
|
|
|
if (!strcmp(arg, "force"))
|
|
|
|
return BLANKSCREEN;
|
2020-04-19 00:16:22 -05:00
|
|
|
if (!strcmp(arg, "poke"))
|
2014-05-17 12:52:01 -05:00
|
|
|
return UNBLANKSCREEN;
|
|
|
|
|
2020-04-19 00:16:22 -05:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = strtos32_or_err(arg, _("argument error"));
|
|
|
|
if (ret < 0 || BLANK_MAX < ret)
|
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
|
|
|
return ret;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2014-05-17 12:52:01 -05:00
|
|
|
static int parse_powersave(const char *arg)
|
|
|
|
{
|
|
|
|
if (strcmp(arg, "on") == 0)
|
|
|
|
return VESA_BLANK_MODE_SUSPENDV;
|
2020-04-19 00:16:22 -05:00
|
|
|
if (strcmp(arg, "vsync") == 0)
|
2014-05-17 12:52:01 -05:00
|
|
|
return VESA_BLANK_MODE_SUSPENDV;
|
2020-04-19 00:16:22 -05:00
|
|
|
if (strcmp(arg, "hsync") == 0)
|
2014-05-17 12:52:01 -05:00
|
|
|
return VESA_BLANK_MODE_SUSPENDH;
|
2020-04-19 00:16:22 -05:00
|
|
|
if (strcmp(arg, "powerdown") == 0)
|
2014-05-17 12:52:01 -05:00
|
|
|
return VESA_BLANK_MODE_POWERDOWN;
|
2020-04-19 00:16:22 -05:00
|
|
|
if (strcmp(arg, "off") == 0)
|
2014-05-17 12:52:01 -05:00
|
|
|
return VESA_BLANK_MODE_OFF;
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
2006-12-06 17:25:34 -06:00
|
|
|
}
|
|
|
|
|
2014-05-17 12:52:01 -05:00
|
|
|
static int parse_msglevel(const char *arg)
|
|
|
|
{
|
2014-05-17 13:21:34 -05:00
|
|
|
int ret;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-17 13:21:34 -05:00
|
|
|
ret = strtos32_or_err(arg, _("argument error"));
|
2014-05-17 12:52:01 -05:00
|
|
|
if (ret < CONSOLE_LEVEL_MIN || CONSOLE_LEVEL_MAX < ret)
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
2014-05-17 12:52:01 -05:00
|
|
|
return ret;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static int parse_snap(char **av, char *oa, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
2014-05-17 13:21:34 -05:00
|
|
|
int ret;
|
2014-05-17 12:52:01 -05:00
|
|
|
char *arg;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
arg = find_optional_arg(av, oa, oi);
|
2014-05-17 12:52:01 -05:00
|
|
|
if (!arg)
|
|
|
|
return 0;
|
2014-05-17 13:21:34 -05:00
|
|
|
ret = strtos32_or_err(arg, _("argument error"));
|
2014-05-17 12:52:01 -05:00
|
|
|
if (ret < 1)
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
2014-05-17 12:52:01 -05:00
|
|
|
return ret;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static void parse_tabs(char **av, char *oa, int *oi, int *tab_array)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
int i = 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
if (oa) {
|
|
|
|
tab_array[i] = strtos32_or_err(oa, _("argument error"));
|
2014-05-17 12:52:01 -05:00
|
|
|
i++;
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2016-07-03 07:13:21 -05:00
|
|
|
while (av[*oi]) {
|
2014-05-17 12:52:01 -05:00
|
|
|
if (TABS_MAX < i)
|
|
|
|
errx(EXIT_FAILURE, _("too many tabs"));
|
2016-07-03 07:13:21 -05:00
|
|
|
if (av[*oi][0] == '-')
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
2016-07-03 07:13:21 -05:00
|
|
|
tab_array[i] = strtos32_or_err(av[*oi], _("argument error"));
|
|
|
|
(*oi)++;
|
2014-05-17 12:52:01 -05:00
|
|
|
i++;
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2014-05-17 12:52:01 -05:00
|
|
|
tab_array[i] = -1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static int parse_regtabs(char **av, char *oa, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
char *arg;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
arg = find_optional_arg(av, oa, oi);
|
2014-05-17 12:52:01 -05:00
|
|
|
if (!arg)
|
|
|
|
return DEFAULT_TAB_LEN;
|
2014-05-17 13:21:34 -05:00
|
|
|
ret = strtos32_or_err(arg, _("argument error"));
|
2014-05-17 12:52:01 -05:00
|
|
|
if (ret < 1 || TABS_MAX < ret)
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
2014-05-17 12:52:01 -05:00
|
|
|
return ret;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static int parse_blength(char **av, char *oa, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *arg;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
arg = find_optional_arg(av, oa, oi);
|
2014-05-17 12:52:01 -05:00
|
|
|
if (!arg)
|
|
|
|
return 0;
|
2014-05-17 13:21:34 -05:00
|
|
|
ret = strtos32_or_err(arg, _("argument error"));
|
2014-05-17 12:52:01 -05:00
|
|
|
if (ret < 0 || BLENGTH_MAX < ret)
|
2016-05-08 15:17:18 -05:00
|
|
|
errx(EXIT_FAILURE, "%s: %s", _("argument error"), arg);
|
2014-05-17 12:52:01 -05:00
|
|
|
return ret;
|
2006-12-06 17:25:34 -06:00
|
|
|
}
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static int parse_bfreq(char **av, char *oa, int *oi)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
char *arg;
|
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
arg = find_optional_arg(av, oa, oi);
|
2014-05-17 12:52:01 -05:00
|
|
|
if (!arg)
|
|
|
|
return 0;
|
2014-05-17 13:21:34 -05:00
|
|
|
return strtos32_or_err(arg, _("argument error"));
|
2006-12-06 17:25:34 -06:00
|
|
|
}
|
|
|
|
|
2017-06-19 13:52:50 -05:00
|
|
|
static void __attribute__((__noreturn__)) usage(void)
|
2014-05-18 06:37:24 -05:00
|
|
|
{
|
2017-06-19 13:52:50 -05:00
|
|
|
FILE *out = stdout;
|
2014-05-18 06:37:24 -05:00
|
|
|
fputs(USAGE_HEADER, out);
|
2011-08-16 06:50:29 -05:00
|
|
|
fprintf(out,
|
|
|
|
_(" %s [options]\n"), program_invocation_short_name);
|
2014-12-22 15:57:17 -06:00
|
|
|
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
fputs(_("Set the attributes of a terminal.\n"), out);
|
|
|
|
|
2014-05-18 06:37:24 -05:00
|
|
|
fputs(USAGE_OPTIONS, out);
|
2019-09-10 05:14:25 -05:00
|
|
|
fputs(_(" --term <terminal_name> override TERM environment variable\n"), out);
|
|
|
|
fputs(_(" --reset reset terminal to power-on state\n"), out);
|
|
|
|
fputs(_(" --resize reset terminal rows and columns\n"), out);
|
|
|
|
fputs(_(" --initialize display init string, and use default settings\n"), out);
|
|
|
|
fputs(_(" --default use default terminal settings\n"), out);
|
|
|
|
fputs(_(" --store save current terminal settings as default\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --cursor on|off display cursor\n"), out);
|
|
|
|
fputs(_(" --repeat on|off keyboard repeat\n"), out);
|
|
|
|
fputs(_(" --appcursorkeys on|off cursor key application mode\n"), out);
|
|
|
|
fputs(_(" --linewrap on|off continue on a new line when a line is full\n"), out);
|
|
|
|
fputs(_(" --inversescreen on|off swap colors for the whole screen\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --msg on|off send kernel messages to console\n"), out);
|
|
|
|
fputs(_(" --msglevel <0-8> kernel console log level\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --foreground default|<color> set foreground color\n"), out);
|
|
|
|
fputs(_(" --background default|<color> set background color\n"), out);
|
|
|
|
fputs(_(" --ulcolor [bright] <color> set underlined text color\n"), out);
|
|
|
|
fputs(_(" --hbcolor [bright] <color> set half-bright text color\n"), out);
|
|
|
|
fputs(_(" <color>: black blue cyan green grey magenta red white yellow\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --bold on|off bold\n"), out);
|
|
|
|
fputs(_(" --half-bright on|off dim\n"), out);
|
|
|
|
fputs(_(" --blink on|off blink\n"), out);
|
|
|
|
fputs(_(" --underline on|off underline\n"), out);
|
|
|
|
fputs(_(" --reverse on|off swap foreground and background colors\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --clear[=<all|rest>] clear screen and set cursor position\n"), out);
|
|
|
|
fputs(_(" --tabs[=<number>...] set these tab stop positions, or show them\n"), out);
|
|
|
|
fputs(_(" --clrtabs[=<number>...] clear these tab stop positions, or all\n"), out);
|
|
|
|
fputs(_(" --regtabs[=1-160] set a regular tab stop interval\n"), out);
|
|
|
|
fputs(_(" --blank[=0-60|force|poke] set time of inactivity before screen blanks\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --dump[=<number>] write vcsa<number> console dump to file\n"), out);
|
|
|
|
fputs(_(" --append <number> append vcsa<number> console dump to file\n"), out);
|
|
|
|
fputs(_(" --file <filename> name of the dump file\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --powersave on|vsync|hsync|powerdown|off\n"), out);
|
|
|
|
fputs(_(" set vesa powersaving features\n"), out);
|
|
|
|
fputs(_(" --powerdown[=<0-60>] set vesa powerdown interval in minutes\n"), out);
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
|
|
|
|
fputs(_(" --blength[=<0-2000>] duration of the bell in milliseconds\n"), out);
|
|
|
|
fputs(_(" --bfreq[=<number>] bell frequency in Hertz\n"), out);
|
|
|
|
|
|
|
|
fputs(USAGE_SEPARATOR, out);
|
|
|
|
printf( " --help %s\n", USAGE_OPTSTR_HELP);
|
|
|
|
printf( " --version %s\n", USAGE_OPTSTR_VERSION);
|
2017-06-25 07:49:47 -05:00
|
|
|
|
2017-06-29 08:52:16 -05:00
|
|
|
printf(USAGE_MAN_TAIL("setterm(1)"));
|
2017-06-19 13:52:50 -05:00
|
|
|
exit(EXIT_SUCCESS);
|
2011-04-02 15:56:51 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-18 03:35:01 -05:00
|
|
|
static int __attribute__((__pure__)) set_opt_flag(int opt)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
2014-05-18 03:35:01 -05:00
|
|
|
if (opt)
|
2014-05-17 12:52:01 -05:00
|
|
|
errx(EXIT_FAILURE, _("duplicate use of an option"));
|
2014-05-18 03:35:01 -05:00
|
|
|
return 1;
|
2014-05-17 12:52:01 -05:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
static void parse_option(struct setterm_control *ctl, int ac, char **av)
|
2014-05-17 12:52:01 -05:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
enum {
|
|
|
|
OPT_TERM = CHAR_MAX + 1,
|
|
|
|
OPT_RESET,
|
2016-12-29 04:28:54 -06:00
|
|
|
OPT_RESIZE,
|
2014-05-17 12:52:01 -05:00
|
|
|
OPT_INITIALIZE,
|
|
|
|
OPT_CURSOR,
|
|
|
|
OPT_REPEAT,
|
|
|
|
OPT_APPCURSORKEYS,
|
|
|
|
OPT_LINEWRAP,
|
|
|
|
OPT_DEFAULT,
|
|
|
|
OPT_FOREGROUND,
|
|
|
|
OPT_BACKGROUND,
|
|
|
|
OPT_ULCOLOR,
|
|
|
|
OPT_HBCOLOR,
|
|
|
|
OPT_INVERSESCREEN,
|
|
|
|
OPT_BOLD,
|
|
|
|
OPT_HALF_BRIGHT,
|
|
|
|
OPT_BLINK,
|
|
|
|
OPT_REVERSE,
|
|
|
|
OPT_UNDERLINE,
|
|
|
|
OPT_STORE,
|
|
|
|
OPT_CLEAR,
|
|
|
|
OPT_TABS,
|
|
|
|
OPT_CLRTABS,
|
|
|
|
OPT_REGTABS,
|
|
|
|
OPT_BLANK,
|
|
|
|
OPT_DUMP,
|
|
|
|
OPT_APPEND,
|
|
|
|
OPT_FILE,
|
|
|
|
OPT_MSG,
|
|
|
|
OPT_MSGLEVEL,
|
|
|
|
OPT_POWERSAVE,
|
|
|
|
OPT_POWERDOWN,
|
|
|
|
OPT_BLENGTH,
|
|
|
|
OPT_BFREQ,
|
|
|
|
OPT_VERSION,
|
|
|
|
OPT_HELP
|
|
|
|
};
|
|
|
|
static const struct option longopts[] = {
|
|
|
|
{"term", required_argument, NULL, OPT_TERM},
|
|
|
|
{"reset", no_argument, NULL, OPT_RESET},
|
2016-12-29 04:28:54 -06:00
|
|
|
{"resize", no_argument, NULL, OPT_RESIZE},
|
2014-05-17 12:52:01 -05:00
|
|
|
{"initialize", no_argument, NULL, OPT_INITIALIZE},
|
|
|
|
{"cursor", required_argument, NULL, OPT_CURSOR},
|
|
|
|
{"repeat", required_argument, NULL, OPT_REPEAT},
|
|
|
|
{"appcursorkeys", required_argument, NULL, OPT_APPCURSORKEYS},
|
|
|
|
{"linewrap", required_argument, NULL, OPT_LINEWRAP},
|
|
|
|
{"default", no_argument, NULL, OPT_DEFAULT},
|
|
|
|
{"foreground", required_argument, NULL, OPT_FOREGROUND},
|
|
|
|
{"background", required_argument, NULL, OPT_BACKGROUND},
|
|
|
|
{"ulcolor", required_argument, NULL, OPT_ULCOLOR},
|
|
|
|
{"hbcolor", required_argument, NULL, OPT_HBCOLOR},
|
|
|
|
{"inversescreen", required_argument, NULL, OPT_INVERSESCREEN},
|
|
|
|
{"bold", required_argument, NULL, OPT_BOLD},
|
|
|
|
{"half-bright", required_argument, NULL, OPT_HALF_BRIGHT},
|
|
|
|
{"blink", required_argument, NULL, OPT_BLINK},
|
|
|
|
{"reverse", required_argument, NULL, OPT_REVERSE},
|
|
|
|
{"underline", required_argument, NULL, OPT_UNDERLINE},
|
|
|
|
{"store", no_argument, NULL, OPT_STORE},
|
2019-09-10 04:12:38 -05:00
|
|
|
{"clear", optional_argument, NULL, OPT_CLEAR},
|
2014-05-17 12:52:01 -05:00
|
|
|
{"tabs", optional_argument, NULL, OPT_TABS},
|
|
|
|
{"clrtabs", optional_argument, NULL, OPT_CLRTABS},
|
|
|
|
{"regtabs", optional_argument, NULL, OPT_REGTABS},
|
|
|
|
{"blank", optional_argument, NULL, OPT_BLANK},
|
|
|
|
{"dump", optional_argument, NULL, OPT_DUMP},
|
|
|
|
{"append", required_argument, NULL, OPT_APPEND},
|
|
|
|
{"file", required_argument, NULL, OPT_FILE},
|
|
|
|
{"msg", required_argument, NULL, OPT_MSG},
|
|
|
|
{"msglevel", required_argument, NULL, OPT_MSGLEVEL},
|
|
|
|
{"powersave", required_argument, NULL, OPT_POWERSAVE},
|
|
|
|
{"powerdown", optional_argument, NULL, OPT_POWERDOWN},
|
|
|
|
{"blength", optional_argument, NULL, OPT_BLENGTH},
|
|
|
|
{"bfreq", optional_argument, NULL, OPT_BFREQ},
|
|
|
|
{"version", no_argument, NULL, OPT_VERSION},
|
|
|
|
{"help", no_argument, NULL, OPT_HELP},
|
|
|
|
{NULL, 0, NULL, 0}
|
|
|
|
};
|
2014-05-18 08:39:58 -05:00
|
|
|
static const ul_excl_t excl[] = {
|
|
|
|
{ OPT_DEFAULT, OPT_STORE },
|
|
|
|
{ OPT_TABS, OPT_CLRTABS, OPT_REGTABS },
|
|
|
|
{ OPT_MSG, OPT_MSGLEVEL },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
|
2014-05-17 12:52:01 -05:00
|
|
|
|
2016-07-03 07:13:21 -05:00
|
|
|
while ((c = getopt_long_only(ac, av, "", longopts, NULL)) != -1) {
|
2014-05-18 08:39:58 -05:00
|
|
|
err_exclusive_options(c, longopts, excl, excl_st);
|
2014-05-17 12:52:01 -05:00
|
|
|
switch (c) {
|
|
|
|
case OPT_TERM:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_term = set_opt_flag(ctl->opt_term);
|
|
|
|
ctl->opt_te_terminal_name = optarg;
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_RESET:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_reset = set_opt_flag(ctl->opt_reset);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
2016-12-29 04:28:54 -06:00
|
|
|
case OPT_RESIZE:
|
|
|
|
ctl->opt_resize = set_opt_flag(ctl->opt_resize);
|
|
|
|
break;
|
2014-05-17 12:52:01 -05:00
|
|
|
case OPT_INITIALIZE:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_initialize = set_opt_flag(ctl->opt_initialize);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_CURSOR:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_cursor = set_opt_flag(ctl->opt_cursor);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_cu_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_REPEAT:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_repeat = set_opt_flag(ctl->opt_repeat);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_rep_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_APPCURSORKEYS:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_appcursorkeys = set_opt_flag(ctl->opt_appcursorkeys);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_appck_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_LINEWRAP:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_linewrap = set_opt_flag(ctl->opt_linewrap);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_li_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_DEFAULT:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_default = set_opt_flag(ctl->opt_default);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_FOREGROUND:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_foreground = set_opt_flag(ctl->opt_foreground);
|
|
|
|
ctl->opt_fo_color = parse_febg_color(optarg);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_BACKGROUND:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_background = set_opt_flag(ctl->opt_background);
|
|
|
|
ctl->opt_ba_color = parse_febg_color(optarg);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_ULCOLOR:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_ulcolor = set_opt_flag(ctl->opt_ulcolor);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_ul_color = parse_ulhb_color(av, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_HBCOLOR:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_hbcolor = set_opt_flag(ctl->opt_hbcolor);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_hb_color = parse_ulhb_color(av, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_INVERSESCREEN:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_inversescreen = set_opt_flag(ctl->opt_inversescreen);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_invsc_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_BOLD:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_bold = set_opt_flag(ctl->opt_bold);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_bo_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_HALF_BRIGHT:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_halfbright = set_opt_flag(ctl->opt_halfbright);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_hb_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_BLINK:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_blink = set_opt_flag(ctl->opt_blink);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_bl_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_REVERSE:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_reverse = set_opt_flag(ctl->opt_reverse);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_re_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_UNDERLINE:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_underline = set_opt_flag(ctl->opt_underline);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_un_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_STORE:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_store = set_opt_flag(ctl->opt_store);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_CLEAR:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_clear = set_opt_flag(ctl->opt_clear);
|
2019-09-10 04:12:38 -05:00
|
|
|
if (optarg)
|
|
|
|
ctl->opt_cl_all = parse_switch(optarg, _("argument error"),
|
|
|
|
"all", "rest", NULL);
|
|
|
|
else
|
|
|
|
ctl->opt_cl_all = 1;
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_TABS:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_tabs = set_opt_flag(ctl->opt_tabs);
|
2016-07-03 07:13:21 -05:00
|
|
|
parse_tabs(av, optarg, &optind, ctl->opt_tb_array);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_CLRTABS:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_clrtabs = set_opt_flag(ctl->opt_clrtabs);
|
2016-07-03 07:13:21 -05:00
|
|
|
parse_tabs(av, optarg, &optind, ctl->opt_tb_array);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_REGTABS:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_regtabs = set_opt_flag(ctl->opt_regtabs);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_rt_len = parse_regtabs(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_BLANK:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_blank = set_opt_flag(ctl->opt_blank);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_bl_min = parse_blank(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_DUMP:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_snap = set_opt_flag(ctl->opt_snap);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_sn_num = parse_snap(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_APPEND:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_append = set_opt_flag(ctl->opt_append);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_sn_num = parse_snap(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_FILE:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_snapfile = set_opt_flag(ctl->opt_snapfile);
|
|
|
|
ctl->opt_sn_name = optarg;
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_MSG:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_msg = set_opt_flag(ctl->opt_msg);
|
2015-02-24 05:04:22 -06:00
|
|
|
ctl->opt_msg_on = parse_switch(optarg, _("argument error"),
|
|
|
|
"on", "off", NULL);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_MSGLEVEL:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_msglevel = set_opt_flag(ctl->opt_msglevel);
|
|
|
|
ctl->opt_msglevel_num = parse_msglevel(optarg);
|
2014-05-18 06:31:16 -05:00
|
|
|
if (ctl->opt_msglevel_num == 0) {
|
|
|
|
ctl->opt_msg = set_opt_flag(ctl->opt_msg);
|
|
|
|
ctl->opt_msg_on |= 1;
|
|
|
|
}
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_POWERSAVE:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_powersave = set_opt_flag(ctl->opt_powersave);
|
|
|
|
ctl->opt_ps_mode = parse_powersave(optarg);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_POWERDOWN:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_powerdown = set_opt_flag(ctl->opt_powerdown);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_pd_min = parse_blank(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_BLENGTH:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_blength = set_opt_flag(ctl->opt_blength);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_blength_l = parse_blength(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
|
|
|
case OPT_BFREQ:
|
2014-05-18 03:35:01 -05:00
|
|
|
ctl->opt_bfreq = set_opt_flag(ctl->opt_bfreq);
|
2016-07-03 07:13:21 -05:00
|
|
|
ctl->opt_bfreq_f = parse_bfreq(av, optarg, &optind);
|
2014-05-17 12:52:01 -05:00
|
|
|
break;
|
2019-04-16 08:14:13 -05:00
|
|
|
|
2014-05-17 12:52:01 -05:00
|
|
|
case OPT_VERSION:
|
2019-04-16 08:14:13 -05:00
|
|
|
print_version(EXIT_SUCCESS);
|
2014-05-17 12:52:01 -05:00
|
|
|
case OPT_HELP:
|
2017-06-19 13:52:50 -05:00
|
|
|
usage();
|
2014-05-17 12:52:01 -05:00
|
|
|
default:
|
2016-12-19 06:13:34 -06:00
|
|
|
errtryhelp(EXIT_FAILURE);
|
2014-05-17 12:52:01 -05:00
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2014-05-18 07:12:09 -05:00
|
|
|
/* Return the specified terminfo string, or an empty string if no such
|
|
|
|
* terminfo capability exists. */
|
|
|
|
static char *ti_entry(const char *name)
|
|
|
|
{
|
2006-12-06 17:25:43 -06:00
|
|
|
char *buf_ptr;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2018-07-23 04:45:15 -05:00
|
|
|
if ((buf_ptr = tigetstr(name)) == (char *)-1)
|
2006-12-06 17:25:53 -06:00
|
|
|
buf_ptr = NULL;
|
2006-12-06 17:25:43 -06:00
|
|
|
return buf_ptr;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2014-05-17 14:12:23 -05:00
|
|
|
static void show_tabs(void)
|
|
|
|
{
|
|
|
|
int i, co = tigetnum("cols");
|
|
|
|
|
|
|
|
if (co > 0) {
|
|
|
|
printf("\r ");
|
|
|
|
for (i = 10; i < co - 2; i += 10)
|
|
|
|
printf("%-10d", i);
|
|
|
|
putchar('\n');
|
|
|
|
for (i = 1; i <= co; i++)
|
|
|
|
putchar(i % 10 + '0');
|
|
|
|
putchar('\n');
|
|
|
|
for (i = 1; i < co; i++)
|
|
|
|
printf("\tT\b");
|
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-18 05:00:14 -05:00
|
|
|
static int open_snapshot_device(struct setterm_control *ctl)
|
2014-05-17 14:12:23 -05:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
2014-05-18 05:32:04 -05:00
|
|
|
if (ctl->opt_sn_num)
|
|
|
|
xasprintf(&ctl->in_device, "/dev/vcsa%d", ctl->opt_sn_num);
|
|
|
|
else
|
|
|
|
xasprintf(&ctl->in_device, "/dev/vcsa");
|
|
|
|
fd = open(ctl->in_device, O_RDONLY);
|
2014-05-18 05:00:14 -05:00
|
|
|
if (fd < 0)
|
2014-05-18 08:04:03 -05:00
|
|
|
err(EXIT_DUMPFILE, _("cannot read %s"), ctl->in_device);
|
2014-05-18 05:00:14 -05:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2014-05-18 08:55:23 -05:00
|
|
|
static void set_blanking(struct setterm_control *ctl)
|
|
|
|
{
|
|
|
|
char ioctlarg;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (0 <= ctl->opt_bl_min) {
|
|
|
|
printf("\033[9;%d]", ctl->opt_bl_min);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (ctl->opt_bl_min) {
|
|
|
|
case BLANKSCREEN:
|
|
|
|
ioctlarg = TIOCL_BLANKSCREEN;
|
|
|
|
if (ioctl(STDIN_FILENO, TIOCLINUX, &ioctlarg))
|
|
|
|
warn(_("cannot force blank"));
|
|
|
|
break;
|
|
|
|
case UNBLANKSCREEN:
|
|
|
|
ioctlarg = TIOCL_UNBLANKSCREEN;
|
|
|
|
if (ioctl(STDIN_FILENO, TIOCLINUX, &ioctlarg))
|
|
|
|
warn(_("cannot force unblank"));
|
|
|
|
break;
|
|
|
|
case BLANKEDSCREEN:
|
|
|
|
ioctlarg = TIOCL_BLANKEDSCREEN;
|
|
|
|
ret = ioctl(STDIN_FILENO, TIOCLINUX, &ioctlarg);
|
|
|
|
if (ret < 0)
|
|
|
|
warn(_("cannot get blank status"));
|
|
|
|
else
|
|
|
|
printf("%d\n", ret);
|
|
|
|
break;
|
|
|
|
default: /* should be impossible to reach */
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-18 05:00:14 -05:00
|
|
|
static void screendump(struct setterm_control *ctl)
|
|
|
|
{
|
|
|
|
unsigned char header[4];
|
|
|
|
unsigned int rows, cols;
|
|
|
|
int fd;
|
|
|
|
FILE *out;
|
|
|
|
size_t i, j;
|
|
|
|
ssize_t rc;
|
|
|
|
char *inbuf, *outbuf, *p, *q;
|
|
|
|
|
|
|
|
/* open source and destination files */
|
|
|
|
fd = open_snapshot_device(ctl);
|
|
|
|
if (!ctl->opt_sn_name)
|
2014-07-13 11:27:10 -05:00
|
|
|
ctl->opt_sn_name = "screen.dump";
|
2014-05-18 05:00:14 -05:00
|
|
|
out = fopen(ctl->opt_sn_name, ctl->opt_snap ? "w" : "a");
|
|
|
|
if (!out)
|
2016-11-01 13:40:33 -05:00
|
|
|
err(EXIT_DUMPFILE, _("cannot open dump file %s for output"), ctl->opt_sn_name);
|
2014-05-18 05:00:14 -05:00
|
|
|
/* determine snapshot size */
|
2014-05-17 14:12:23 -05:00
|
|
|
if (read(fd, header, 4) != 4)
|
2014-05-18 08:04:03 -05:00
|
|
|
err(EXIT_DUMPFILE, _("cannot read %s"), ctl->in_device);
|
2014-05-17 14:12:23 -05:00
|
|
|
rows = header[0];
|
|
|
|
cols = header[1];
|
|
|
|
if (rows * cols == 0)
|
2014-05-18 08:04:03 -05:00
|
|
|
err(EXIT_DUMPFILE, _("cannot read %s"), ctl->in_device);
|
2014-05-18 05:00:14 -05:00
|
|
|
/* allocate buffers */
|
2014-05-17 14:12:23 -05:00
|
|
|
inbuf = xmalloc(rows * cols * 2);
|
|
|
|
outbuf = xmalloc(rows * (cols + 1));
|
2014-05-18 05:00:14 -05:00
|
|
|
/* read input */
|
2014-05-17 14:12:23 -05:00
|
|
|
rc = read(fd, inbuf, rows * cols * 2);
|
|
|
|
if (rc < 0 || (size_t)rc != rows * cols * 2)
|
2014-05-18 08:04:03 -05:00
|
|
|
err(EXIT_DUMPFILE, _("cannot read %s"), ctl->in_device);
|
2014-05-17 14:12:23 -05:00
|
|
|
p = inbuf;
|
|
|
|
q = outbuf;
|
2014-05-18 05:00:14 -05:00
|
|
|
/* copy inbuf to outbuf */
|
2014-05-17 14:12:23 -05:00
|
|
|
for (i = 0; i < rows; i++) {
|
|
|
|
for (j = 0; j < cols; j++) {
|
|
|
|
*q++ = *p;
|
|
|
|
p += 2;
|
|
|
|
}
|
|
|
|
while (j-- > 0 && q[-1] == ' ')
|
|
|
|
q--;
|
|
|
|
*q++ = '\n';
|
|
|
|
}
|
2014-05-18 05:00:14 -05:00
|
|
|
fwrite(outbuf, 1, q - outbuf, out);
|
|
|
|
/* clean up allocations */
|
2014-05-17 14:12:23 -05:00
|
|
|
close(fd);
|
|
|
|
free(inbuf);
|
|
|
|
free(outbuf);
|
2014-05-18 05:32:04 -05:00
|
|
|
free(ctl->in_device);
|
2014-05-18 05:00:14 -05:00
|
|
|
if (close_stream(out) != 0)
|
|
|
|
errx(EXIT_FAILURE, _("write error"));
|
2014-05-17 14:12:23 -05:00
|
|
|
}
|
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* Some options are applicable when terminal is virtual console. */
|
|
|
|
static int vc_only(struct setterm_control *ctl, const char *err)
|
|
|
|
{
|
2016-07-04 16:09:10 -05:00
|
|
|
if (!ctl->vcterm && err)
|
|
|
|
warnx(_("terminal %s does not support %s"),
|
|
|
|
ctl->opt_te_terminal_name, err);
|
2014-05-18 07:40:11 -05:00
|
|
|
return ctl->vcterm;
|
|
|
|
}
|
|
|
|
|
2016-12-29 04:28:54 -06:00
|
|
|
static void tty_raw(struct termios *saved_attributes, int *saved_fl)
|
|
|
|
{
|
|
|
|
struct termios tattr;
|
|
|
|
|
|
|
|
fcntl(STDIN_FILENO, F_GETFL, saved_fl);
|
|
|
|
tcgetattr(STDIN_FILENO, saved_attributes);
|
|
|
|
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
|
|
|
memcpy(&tattr, saved_attributes, sizeof(struct termios));
|
|
|
|
tattr.c_lflag &= ~(ICANON | ECHO);
|
|
|
|
tattr.c_cc[VMIN] = 1;
|
|
|
|
tattr.c_cc[VTIME] = 0;
|
|
|
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void tty_restore(struct termios *saved_attributes, int *saved_fl)
|
|
|
|
{
|
|
|
|
fcntl(STDIN_FILENO, F_SETFL, *saved_fl);
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, saved_attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int select_wait(void)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
fd_set set;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
FD_ZERO(&set);
|
|
|
|
FD_SET(STDIN_FILENO, &set);
|
|
|
|
tv.tv_sec = 10;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
while ((ret = select(1, &set, NULL, NULL, &tv)) < 0) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
err(EXIT_FAILURE, _("select failed"));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int resizetty(void)
|
|
|
|
{
|
2019-08-28 18:25:57 -05:00
|
|
|
/*
|
2016-12-29 04:28:54 -06:00
|
|
|
* \e7 Save current state (cursor coordinates, attributes,
|
|
|
|
* character sets pointed at by G0, G1).
|
|
|
|
* \e[r Set scrolling region; parameters are top and bottom row.
|
|
|
|
* \e[32766E Move cursor down 32766 (INT16_MAX - 1) rows.
|
|
|
|
* \e[32766C Move cursor right 32766 columns.
|
|
|
|
* \e[6n Report cursor position.
|
|
|
|
* \e8 Restore state most recently saved by \e7.
|
|
|
|
*/
|
|
|
|
static const char *getpos = "\e7\e[r\e[32766E\e[32766C\e[6n\e8";
|
|
|
|
char retstr[32];
|
|
|
|
int row, col;
|
|
|
|
size_t pos;
|
|
|
|
ssize_t rc;
|
|
|
|
struct winsize ws;
|
|
|
|
struct termios saved_attributes;
|
|
|
|
int saved_fl;
|
|
|
|
|
|
|
|
if (!isatty(STDIN_FILENO))
|
|
|
|
errx(EXIT_FAILURE, _("stdin does not refer to a terminal"));
|
|
|
|
|
|
|
|
tty_raw(&saved_attributes, &saved_fl);
|
|
|
|
if (write_all(STDIN_FILENO, getpos, strlen(getpos)) < 0) {
|
|
|
|
warn(_("write failed"));
|
|
|
|
tty_restore(&saved_attributes, &saved_fl);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
for (pos = 0; pos < sizeof(retstr) - 1;) {
|
|
|
|
if (0 == select_wait())
|
|
|
|
break;
|
|
|
|
if ((rc =
|
|
|
|
read(STDIN_FILENO, retstr + pos,
|
|
|
|
sizeof(retstr) - 1 - pos)) < 0) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
warn(_("read failed"));
|
|
|
|
tty_restore(&saved_attributes, &saved_fl);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
pos += rc;
|
|
|
|
if (retstr[pos - 1] == 'R')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
retstr[pos] = 0;
|
|
|
|
tty_restore(&saved_attributes, &saved_fl);
|
|
|
|
rc = sscanf(retstr, "\033[%d;%dR", &row, &col);
|
|
|
|
if (rc != 2) {
|
|
|
|
warnx(_("invalid cursor position: %s"), retstr);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
memset(&ws, 0, sizeof(struct winsize));
|
|
|
|
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
|
|
|
|
ws.ws_row = row;
|
|
|
|
ws.ws_col = col;
|
|
|
|
ioctl(STDIN_FILENO, TIOCSWINSZ, &ws);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-05-18 03:35:01 -05:00
|
|
|
static void perform_sequence(struct setterm_control *ctl)
|
|
|
|
{
|
2006-12-06 17:25:43 -06:00
|
|
|
int result;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -reset. */
|
2014-05-18 07:12:09 -05:00
|
|
|
if (ctl->opt_reset)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("rs1"));
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2016-12-29 04:28:54 -06:00
|
|
|
/* -resize. */
|
|
|
|
if (ctl->opt_resize)
|
|
|
|
if (resizetty())
|
|
|
|
warnx(_("reset failed"));
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -initialize. */
|
2014-05-18 07:12:09 -05:00
|
|
|
if (ctl->opt_initialize)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("is2"));
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -cursor [on|off]. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_cursor) {
|
|
|
|
if (ctl->opt_cu_on)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("cnorm"));
|
|
|
|
else
|
|
|
|
putp(ti_entry("civis"));
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -linewrap [on|off]. */
|
2014-05-18 08:10:21 -05:00
|
|
|
if (ctl->opt_linewrap)
|
2014-05-18 03:35:01 -05:00
|
|
|
fputs(ctl->opt_li_on ? "\033[?7h" : "\033[?7l", stdout);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -repeat [on|off]. */
|
|
|
|
if (ctl->opt_repeat && vc_only(ctl, "--repeat"))
|
2014-05-18 03:35:01 -05:00
|
|
|
fputs(ctl->opt_rep_on ? "\033[?8h" : "\033[?8l", stdout);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -appcursorkeys [on|off]. */
|
|
|
|
if (ctl->opt_appcursorkeys && vc_only(ctl, "--appcursorkeys"))
|
2014-05-18 03:35:01 -05:00
|
|
|
fputs(ctl->opt_appck_on ? "\033[?1h" : "\033[?1l", stdout);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -default. Vc sets default rendition, otherwise clears all
|
2014-05-18 07:12:09 -05:00
|
|
|
* attributes. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_default) {
|
2014-05-18 07:40:11 -05:00
|
|
|
if (vc_only(ctl, NULL))
|
2006-12-06 17:25:43 -06:00
|
|
|
printf("\033[0m");
|
2006-12-06 17:25:32 -06:00
|
|
|
else
|
2006-12-06 17:25:34 -06:00
|
|
|
putp(ti_entry("sgr0"));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -foreground black|red|green|yellow|blue|magenta|cyan|white|default. */
|
2014-05-18 08:10:21 -05:00
|
|
|
if (ctl->opt_foreground)
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[3%c%s", '0' + ctl->opt_fo_color, "m");
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -background black|red|green|yellow|blue|magenta|cyan|white|default. */
|
2014-05-18 08:10:21 -05:00
|
|
|
if (ctl->opt_background)
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[4%c%s", '0' + ctl->opt_ba_color, "m");
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2019-03-07 15:07:37 -06:00
|
|
|
/* -ulcolor [bright] black|red|green|yellow|blue|magenta|cyan|white. */
|
2014-05-18 07:40:11 -05:00
|
|
|
if (ctl->opt_ulcolor && vc_only(ctl, "--ulcolor"))
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[1;%d]", ctl->opt_ul_color);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2019-03-07 15:07:37 -06:00
|
|
|
/* -hbcolor [bright] black|red|green|yellow|blue|magenta|cyan|white. */
|
2014-05-18 08:10:21 -05:00
|
|
|
if (ctl->opt_hbcolor)
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[2;%d]", ctl->opt_hb_color);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -inversescreen [on|off]. */
|
2014-05-18 08:10:21 -05:00
|
|
|
if (ctl->opt_inversescreen)
|
2014-05-18 03:35:01 -05:00
|
|
|
fputs(ctl->opt_invsc_on ? "\033[?5h" : "\033[?5l", stdout);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
/* -bold [on|off]. Vc behaves as expected, otherwise off turns off
|
2014-05-18 07:12:09 -05:00
|
|
|
* all attributes. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_bold) {
|
|
|
|
if (ctl->opt_bo_on)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("bold"));
|
|
|
|
else {
|
2014-05-18 07:40:11 -05:00
|
|
|
if (vc_only(ctl, NULL))
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[22m", stdout);
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
|
|
|
putp(ti_entry("sgr0"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-18 07:12:09 -05:00
|
|
|
/* -half-bright [on|off]. Vc behaves as expected, otherwise off
|
|
|
|
* turns off all attributes. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_halfbright) {
|
|
|
|
if (ctl->opt_hb_on)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("dim"));
|
|
|
|
else {
|
2014-05-18 07:40:11 -05:00
|
|
|
if (vc_only(ctl, NULL))
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[22m", stdout);
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
|
|
|
putp(ti_entry("sgr0"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -blink [on|off]. Vc behaves as expected, otherwise off turns off
|
2014-05-18 07:12:09 -05:00
|
|
|
* all attributes. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_blink) {
|
|
|
|
if (ctl->opt_bl_on)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("blink"));
|
|
|
|
else {
|
2014-05-18 07:40:11 -05:00
|
|
|
if (vc_only(ctl, NULL))
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[25m", stdout);
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
|
|
|
putp(ti_entry("sgr0"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -reverse [on|off]. Vc behaves as expected, otherwise off turns
|
2014-05-18 07:12:09 -05:00
|
|
|
* off all attributes. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_reverse) {
|
|
|
|
if (ctl->opt_re_on)
|
2006-12-06 17:25:43 -06:00
|
|
|
putp(ti_entry("rev"));
|
|
|
|
else {
|
2014-05-18 07:40:11 -05:00
|
|
|
if (vc_only(ctl, NULL))
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[27m", stdout);
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
|
|
|
putp(ti_entry("sgr0"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -underline [on|off]. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_underline)
|
|
|
|
putp(ti_entry(ctl->opt_un_on ? "smul" : "rmul"));
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -store. */
|
|
|
|
if (ctl->opt_store && vc_only(ctl, "--store"))
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[8]", stdout);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
/* -clear [all|rest]. */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_clear)
|
|
|
|
putp(ti_entry(ctl->opt_cl_all ? "clear" : "ed"));
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -tabs. */
|
2014-05-18 08:10:21 -05:00
|
|
|
if (ctl->opt_tabs) {
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_tb_array[0] == -1)
|
2006-12-06 17:25:43 -06:00
|
|
|
show_tabs();
|
|
|
|
else {
|
2014-05-18 08:10:21 -05:00
|
|
|
int i;
|
|
|
|
|
2014-05-18 07:12:09 -05:00
|
|
|
for (i = 0; ctl->opt_tb_array[i] > 0; i++)
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[%dG\033H", ctl->opt_tb_array[i]);
|
2006-12-06 17:25:43 -06:00
|
|
|
putchar('\r');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -clrtabs. */
|
|
|
|
if (ctl->opt_clrtabs && vc_only(ctl, "--clrtabs")) {
|
2006-12-06 17:25:43 -06:00
|
|
|
int i;
|
|
|
|
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_tb_array[0] == -1)
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[3g", stdout);
|
2006-12-06 17:25:32 -06:00
|
|
|
else
|
2014-05-18 07:12:09 -05:00
|
|
|
for (i = 0; ctl->opt_tb_array[i] > 0; i++)
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[%dG\033[g", ctl->opt_tb_array[i]);
|
2006-12-06 17:25:43 -06:00
|
|
|
putchar('\r');
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2014-05-18 07:40:11 -05:00
|
|
|
/* -regtabs. */
|
|
|
|
if (ctl->opt_regtabs && vc_only(ctl, "--regtabs")) {
|
2006-12-06 17:25:43 -06:00
|
|
|
int i;
|
|
|
|
|
2014-05-12 06:53:10 -05:00
|
|
|
fputs("\033[3g\r", stdout);
|
2014-05-18 07:12:09 -05:00
|
|
|
for (i = ctl->opt_rt_len + 1; i <= TABS_MAX; i += ctl->opt_rt_len)
|
|
|
|
printf("\033[%dC\033H", ctl->opt_rt_len);
|
2006-12-06 17:25:43 -06:00
|
|
|
putchar('\r');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -blank [0-60]. */
|
2014-05-18 08:55:23 -05:00
|
|
|
if (ctl->opt_blank && vc_only(ctl, "--blank"))
|
|
|
|
set_blanking(ctl);
|
2007-11-27 16:54:35 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -powersave [on|vsync|hsync|powerdown|off] (console) */
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_powersave) {
|
2006-12-06 17:25:43 -06:00
|
|
|
char ioctlarg[2];
|
2007-11-27 16:54:35 -06:00
|
|
|
ioctlarg[0] = TIOCL_SETVESABLANK;
|
2014-05-18 03:35:01 -05:00
|
|
|
ioctlarg[1] = ctl->opt_ps_mode;
|
2014-05-18 07:12:09 -05:00
|
|
|
if (ioctl(STDIN_FILENO, TIOCLINUX, ioctlarg))
|
2011-04-02 15:56:52 -05:00
|
|
|
warn(_("cannot (un)set powersave mode"));
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -powerdown [0-60]. */
|
2014-05-18 07:12:09 -05:00
|
|
|
if (ctl->opt_powerdown)
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[14;%d]", ctl->opt_pd_min);
|
2006-12-06 17:25:34 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -snap [1-NR_CONS]. */
|
2014-05-18 07:12:09 -05:00
|
|
|
if (ctl->opt_snap || ctl->opt_append)
|
2014-05-18 05:00:14 -05:00
|
|
|
screendump(ctl);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2014-05-18 07:12:09 -05:00
|
|
|
/* -msg [on|off]. Controls printk's to console. */
|
2014-05-18 07:40:11 -05:00
|
|
|
if (ctl->opt_msg && vc_only(ctl, "--msg")) {
|
2014-05-18 03:35:01 -05:00
|
|
|
if (ctl->opt_msg_on)
|
2014-05-11 14:26:49 -05:00
|
|
|
result = klogctl(SYSLOG_ACTION_CONSOLE_ON, NULL, 0);
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
2014-05-11 14:26:49 -05:00
|
|
|
result = klogctl(SYSLOG_ACTION_CONSOLE_OFF, NULL, 0);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
if (result != 0)
|
2011-04-02 15:56:52 -05:00
|
|
|
warn(_("klogctl error"));
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
|
|
|
|
2014-05-18 07:12:09 -05:00
|
|
|
/* -msglevel [0-8]. Console printk message level. */
|
2014-05-18 07:40:11 -05:00
|
|
|
if (ctl->opt_msglevel_num && vc_only(ctl, "--msglevel")) {
|
2014-05-18 07:12:09 -05:00
|
|
|
result =
|
|
|
|
klogctl(SYSLOG_ACTION_CONSOLE_LEVEL, NULL,
|
|
|
|
ctl->opt_msglevel_num);
|
2006-12-06 17:25:43 -06:00
|
|
|
if (result != 0)
|
2011-04-02 15:56:52 -05:00
|
|
|
warn(_("klogctl error"));
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -blength [0-2000] */
|
2014-05-18 07:40:11 -05:00
|
|
|
if (ctl->opt_blength && vc_only(ctl, "--blength")) {
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[11;%d]", ctl->opt_blength_l);
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2009-10-15 18:40:58 -05:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* -bfreq freqnumber */
|
2014-05-18 07:40:11 -05:00
|
|
|
if (ctl->opt_bfreq && vc_only(ctl, "--bfreq")) {
|
2014-05-18 03:35:01 -05:00
|
|
|
printf("\033[10;%d]", ctl->opt_bfreq_f);
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2014-05-18 03:54:12 -05:00
|
|
|
static void init_terminal(struct setterm_control *ctl)
|
2014-05-18 03:35:01 -05:00
|
|
|
{
|
|
|
|
int term_errno;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-18 03:54:12 -05:00
|
|
|
if (!ctl->opt_te_terminal_name) {
|
|
|
|
ctl->opt_te_terminal_name = getenv("TERM");
|
|
|
|
if (ctl->opt_te_terminal_name == NULL)
|
2011-04-02 15:56:52 -05:00
|
|
|
errx(EXIT_FAILURE, _("$TERM is not defined."));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* Find terminfo entry. */
|
2014-05-18 03:54:12 -05:00
|
|
|
if (setupterm(ctl->opt_te_terminal_name, STDOUT_FILENO, &term_errno))
|
|
|
|
switch (term_errno) {
|
2011-04-02 15:56:52 -05:00
|
|
|
case -1:
|
|
|
|
errx(EXIT_FAILURE, _("terminfo database cannot be found"));
|
|
|
|
case 0:
|
2014-05-18 03:54:12 -05:00
|
|
|
errx(EXIT_FAILURE, _("%s: unknown terminal type"), ctl->opt_te_terminal_name);
|
2011-04-02 15:56:52 -05:00
|
|
|
case 1:
|
|
|
|
errx(EXIT_FAILURE, _("terminal is hardcopy"));
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* See if the terminal is a virtual console terminal. */
|
2014-05-18 03:54:12 -05:00
|
|
|
ctl->vcterm = (!strncmp(ctl->opt_te_terminal_name, "con", 3) ||
|
|
|
|
!strncmp(ctl->opt_te_terminal_name, "linux", 5));
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2014-05-18 03:54:12 -05:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2017-02-11 14:23:26 -06:00
|
|
|
struct setterm_control ctl = { NULL };
|
2014-05-18 03:54:12 -05:00
|
|
|
|
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
textdomain(PACKAGE);
|
2019-04-16 08:14:13 -05:00
|
|
|
close_stdout_atexit();
|
2014-05-18 03:54:12 -05:00
|
|
|
|
2017-06-19 13:52:50 -05:00
|
|
|
if (argc < 2) {
|
|
|
|
warnx(_("bad usage"));
|
|
|
|
errtryhelp(EXIT_FAILURE);
|
|
|
|
}
|
2014-05-18 03:54:12 -05:00
|
|
|
parse_option(&ctl, argc, argv);
|
|
|
|
init_terminal(&ctl);
|
2014-05-18 03:35:01 -05:00
|
|
|
perform_sequence(&ctl);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2011-04-02 15:56:52 -05:00
|
|
|
return EXIT_SUCCESS;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|