Fix ioctl issues on DragonFly BSD and FreeBSD (#78)

* Fix ioctl issues on DragonFly BSD and FreeBSD

* Include the correct headers on DragonFly BSD and FreeBSD.

* Use UTF-8 characters to draw border on Linux.

* Use ioctl 'KDGETLED' to get the keyboard LED states, which is supported
  on both Linux and BSD.

* Use macros 'LED_NUM' and 'LED_CAP' instead of hard-coded magic numbers.

NOTE:
This patch only allows 'ly' to build fine on DragonFly BSD and FreeBSD
(other *BSD not tested), and more works are needed to make 'ly' working
fine on BSD.

* Use ioctl 'KDGKBLED' on Linux

The legacy ioctl 'KDGETLED' (which also exists on BSD) is used to get the
state of keyboard LEDs, which, however, can be used to display arbitrary
information!  So the new ioctl 'KDGKBLED' should be used to get the keyboard
flags (CapsLock, NumLock, ScrollLock), and this ioctl has a separate set of
macros ('K_NUMLOCK', 'K_CAPSLOCK') to check the flags.

See the ioctl_console(2) man page for more details.
This commit is contained in:
Aaron LI 2018-10-07 22:42:56 +08:00 committed by Cylgom
parent 5e7437b8e9
commit 4f8c2f2428
2 changed files with 36 additions and 14 deletions

View File

@ -4,21 +4,29 @@
#include "util.h" #include "util.h"
#include "config.h" #include "config.h"
#include "widgets.h" #include "widgets.h"
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#if defined(__DragonFly__) || defined(__FreeBSD__)
# include <sys/kbio.h>
#else /* assume Linux */
# include <linux/kd.h>
#endif
#if defined(__linux__)
// border chars: ┌ └ ┐ ┘ ─ ─ │ │ // border chars: ┌ └ ┐ ┘ ─ ─ │ │
struct box box_main = {0x250c, 0x2514, 0x2510, 0x2518, 0x2500, 0x2500 ,0x2502, 0x2502}; struct box box_main = {0x250c, 0x2514, 0x2510, 0x2518, 0x2500, 0x2500 ,0x2502, 0x2502};
// alternative border chars: #else /* no UTF-8 */
// struct box box_main = {'+', '+', '+', '+', '-', '-', '|', '|'}; struct box box_main = {'+', '+', '+', '+', '-', '-', '|', '|'};
#endif
u16 width = 0; u16 width = 0;
u16 height = 0; u16 height = 0;
@ -207,23 +215,33 @@ void draw_f_commands()
// numlock and capslock info // numlock and capslock info
void draw_lock_state() void draw_lock_state()
{ {
FILE* console = fopen(config.console_dev, "w"); int fd;
if ((fd = open(config.console_dev, O_RDONLY)) < 0)
if (console == NULL)
{ {
info_line = lang.err_console_dev; info_line = lang.err_console_dev;
return; return;
} }
int fd = fileno(console); bool numlock_on;
char ret; bool capslock_on;
ioctl(fd, KDGKBLED, &ret); #if defined(__DragonFly__) || defined(__FreeBSD__)
fclose(console); int led;
ioctl(fd, KDGETLED, &led);
numlock_on = led & LED_NUM;
capslock_on = led & LED_CAP;
#else /* Linux */
char led;
ioctl(fd, KDGKBLED, &led);
numlock_on = led & K_NUMLOCK;
capslock_on = led & K_CAPSLOCK;
#endif
close(fd);
u16 pos_x = width - strlen(lang.numlock); u16 pos_x = width - strlen(lang.numlock);
if (((ret >> 1) & 0x01) == 1) if (numlock_on)
{ {
struct tb_cell* numlock = str_cell(lang.numlock); struct tb_cell* numlock = str_cell(lang.numlock);
tb_blit(pos_x, 0, strlen(lang.numlock), 1, numlock); tb_blit(pos_x, 0, strlen(lang.numlock), 1, numlock);
@ -232,7 +250,7 @@ void draw_lock_state()
pos_x -= strlen(lang.capslock) + 1; pos_x -= strlen(lang.capslock) + 1;
if (((ret >> 2) & 0x01) == 1) if (capslock_on)
{ {
struct tb_cell* capslock = str_cell(lang.capslock); struct tb_cell* capslock = str_cell(lang.capslock);
tb_blit(pos_x, 0, strlen(lang.capslock), 1, capslock); tb_blit(pos_x, 0, strlen(lang.capslock), 1, capslock);

View File

@ -14,7 +14,11 @@
#include <unistd.h> #include <unistd.h>
#include <netdb.h> #include <netdb.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#if defined(__DragonFly__) || defined(__FreeBSD__)
# include <sys/consio.h>
#else /* assume Linux */
# include <linux/vt.h> # include <linux/vt.h>
#endif
static char* hostname_backup = NULL; static char* hostname_backup = NULL;