/
niceSOFT
/
kbd
Обзор
Документация
Войти
/
niceSOFT
/
kbd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/setleds.c
366 строк
8 KB
Alexey Gladkov
Create ARRAY_SIZE() macros
18 мар 2025, 20:11
Не верифицирован
18 мар 2025, 20:11
d3ef079
Код
Авторство
О чём код?
/* * setleds.c - aeb, 940130, 940909, 991008 */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <sysexits.h> #include <linux/kd.h> #include <sys/ioctl.h> #include "array_size.h" #include "libcommon.h" /** * BITWISE_NOT is the bitwise complement of x with cancelled out integer * promotions. */ #define BITWISE_NOT(x) (_Generic((x), \ unsigned char: (unsigned char)(~(x)) \ )) #define BITMASK_UNSET(x, mask) ((x) & BITWISE_NOT(mask)) #define BITMASK_SET(x, mask) ((x) | (mask)) static void KBD_ATTR_NORETURN usage(int rc, const struct kbd_help *options) { fprintf(stderr, _("Usage: %s [option...] [[+|-][ num | caps | scroll %s]]\n"), program_invocation_short_name, #ifdef __sparc__ "| compose " #else "" #endif ); fprintf(stderr, "\n"); fprintf(stderr, _("Thus,\n" " setleds +caps -num\n" "will set CapsLock, clear NumLock and leave ScrollLock unchanged.\n" "The settings before and after the change (if any) are reported\n" "when the -v option is given or when no change is requested.\n" "Normally, setleds influences the vt flag settings\n" "(and these are usually reflected in the leds).\n" "With -L, setleds only sets the leds, and leaves the flags alone.\n" "With -D, setleds sets both the flags and the default flags, so\n" "that a subsequent reset will not change the flags.\n")); print_options(options); print_report_bugs(); exit(rc); } #define onoff(a) ((a) ? _("on ") : _("off")) /* report the bits, in the order seen on the (my) keyboard */ #define LED_NLOCK 1 #define LED_CMPOSE 2 #define LED_SCRLCK 4 #define LED_CLOCK 8 static void sunreport(int leds) { printf("NumLock %s Compose %s ScrollLock %s CapsLock %s\n", onoff(leds & LED_NLOCK), onoff(leds & LED_CMPOSE), onoff(leds & LED_SCRLCK), onoff(leds & LED_CLOCK)); } static void report(int leds) { printf("NumLock %s CapsLock %s ScrollLock %s\n", onoff(leds & LED_NUM), onoff(leds & LED_CAP), onoff(leds & LED_SCR)); } static struct led { const char *name; unsigned char bit; unsigned char sunbit; } leds[] = { { "scroll", LED_SCR, LED_SCRLCK }, { "num", LED_NUM, LED_NLOCK }, { "caps", LED_CAP, LED_CLOCK }, #ifdef __sparc__ { "compose", 0, LED_CMPOSE } #endif }; static void getleds(unsigned char *cur_leds) { if (ioctl(0, KDGETLED, cur_leds)) { kbd_error(EX_OSERR, errno, _("Error reading current led setting. " "Maybe stdin is not a VT?: " "ioctl KDGETLED")); } } static int setleds(unsigned char cur_leds) { if (ioctl(0, KDSETLED, cur_leds)) { kbd_warning(errno, "ioctl KDSETLED"); return -1; } return 0; } static void getflags(unsigned char *flags) { if (ioctl(0, KDGKBLED, flags)) kbd_error(EX_OSERR, errno, _("Unable to read keyboard flags")); } static int sunkbdfd = -1; static void sungetleds(unsigned char *cur_leds KBD_ATTR_UNUSED) { #ifdef KIOCGLED if (ioctl(sunkbdfd, KIOCGLED, cur_leds)) { kbd_error(EX_OSERR, errno, _("Error reading current led setting from /dev/kbd: " "ioctl %s"), "KIOCGLED"); } #else kbd_error(EX_OSERR, 0, _("ioctl %s unavailable?"), "KIOCGLED"); #endif } static void sunsetleds(unsigned char *cur_leds KBD_ATTR_UNUSED) { #ifdef KIOCSLED if (ioctl(sunkbdfd, KIOCSLED, cur_leds)) { kbd_error(EX_OSERR, errno, _("Error reading current led setting from /dev/kbd: " "ioctl %s"), "KIOCSLED"); } #else kbd_error(EX_OSERR, 0, _("ioctl %s unavailable?"), "KIOCSLED"); #endif } static int parse_let_option(char *ap, unsigned char *nval, unsigned char *ndef, unsigned char *nsunval, unsigned char *nsundef) { struct led *lp; unsigned char sign = 1; switch (ap[0]) { case '+': /* by default: set */ ap++; break; case '-': sign = 0; ap++; break; } for (lp = leds; (unsigned)(lp - leds) < ARRAY_SIZE(leds); lp++) { if (!strcmp(ap, lp->name)) { if (sign) { *nval |= lp->bit; *nsunval |= lp->sunbit; } *ndef |= lp->bit; *nsundef |= lp->sunbit; return 0; } } return -1; } struct kbd_option { const char *shrtopt; const char *longopt; int val; }; int main(int argc, char **argv) { int has_changes = 0; int optL = 0, optD = 0, optF = 0, verbose = 0; unsigned char oleds, nleds, oflags, nflags, odefflags, ndefflags; unsigned char nval, ndef; unsigned char osunleds = 0, nsunleds, nsunval, nsundef; setuplocale(); const struct kbd_option opts[] = { { "-D", "--default", 'D' }, { "-F", "--flags", 'F' }, { "-L", "--leds", 'L' }, { "-h", "--help", 'h' }, { "-v", "--verbose", 'v' }, { "-V", "--version", 'V' }, { NULL, NULL, 0 } }; const struct kbd_help opthelp[] = { { "-D, --default", _("change both the VT flags and their default settings.") }, { "-F, --flags", _("change the VT flags.") }, { "-L, --leds", _("change only the leds.") }, { "-V, --version", _("print version number.") }, { "-v, --verbose", _("be more verbose.") }, { "-h, --help", _("print this usage message.") }, { NULL, NULL } }; nval = 0; ndef = 0; nsunval = 0; nsundef = 0; while (argc > 1) { const struct kbd_option *opt; for (opt = opts; opt->longopt; opt++) { if (strcmp(argv[1], opt->shrtopt) && strcmp(argv[1], opt->longopt)) continue; switch (opt->val) { case 'D': optD = 1; break; case 'F': optF = 1; break; case 'L': optL = 1; break; case 'v': verbose = 1; break; case 'V': print_version_and_exit(); break; case 'h': usage(EX_OK, opthelp); break; default: kbd_warning(0, _("Unrecognized argument: %s"), argv[1]); usage(EX_USAGE, opthelp); } goto next_arg; } if (parse_let_option(argv[1], &nval, &ndef, &nsunval, &nsundef) < 0) { kbd_warning(0, _("Unrecognized argument: %s"), argv[1]); usage(EX_USAGE, opthelp); } has_changes = 1; next_arg: argc--; argv++; } #ifdef __sparc__ if ((sunkbdfd = open("/dev/kbd", O_RDONLY)) < 0) { kbd_error(EX_OSFILE, errno, "open /dev/kbd"); /* exit(1); */ } #endif getflags(&oflags); getleds(&oleds); if (sunkbdfd >= 0) sungetleds(&osunleds); odefflags = ndefflags = ((oflags >> 4) & 7); oflags = nflags = (oflags & 7); if (!has_changes) { if (optL) { nleds = 0xff; if (setleds(nleds)) { kbd_error(EX_OSERR, 0, _("Error resetting ledmode")); } } /* If nothing to do, report, even if not verbose */ if (!optD && !optL && !optF) optD = optL = optF = 1; if (optD) { printf(_("Current default flags: ")); report(odefflags); } if (optF) { printf(_("Current flags: ")); report(oflags & 07); } if (optL) { printf(_("Current leds: ")); if (sunkbdfd >= 0) sunreport(osunleds); else report(oleds); } return EX_OK; } if (!optL) optF = 1; if (optD) { ndefflags = BITMASK_SET(BITMASK_UNSET(odefflags, ndef), nval); if (verbose) { printf(_("Old default flags: ")); report(odefflags); printf(_("New default flags: ")); report(ndefflags); } } if (optF) { nflags = BITMASK_SET(BITMASK_UNSET(oflags, ndef), nval); if (verbose) { printf(_("Old flags: ")); report(oflags & 07); printf(_("New flags: ")); report(nflags & 07); } } if (optD || optF) { if (ioctl(0, KDSKBLED, (ndefflags << 4) | nflags)) { kbd_error(EX_OSERR, errno, "ioctl KDSKBLED"); } } if (optL) { if (sunkbdfd >= 0) { nsunleds = BITMASK_SET(BITMASK_UNSET(osunleds, nsundef), nsunval); if (verbose) { printf(_("Old leds: ")); sunreport(osunleds); printf(_("New leds: ")); sunreport(nsunleds); } sunsetleds(&nsunleds); } else { nleds = BITMASK_SET(BITMASK_UNSET(oleds, ndef), nval); if (verbose) { printf(_("Old leds: ")); report(oleds); printf(_("New leds: ")); report(nleds); } if (setleds(nleds)) return EX_OSERR; } } return EX_OK; }