summaryrefslogtreecommitdiffstats
path: root/sys-utils/rfkill.c
diff options
context:
space:
mode:
authorKarel Zak2017-10-03 14:31:57 +0200
committerKarel Zak2017-10-03 14:31:57 +0200
commit49f4f7b6c5018c53b84e55f7105a42bfab337249 (patch)
tree4c7f011f70e3f6f2036b9a646e51d2f659639543 /sys-utils/rfkill.c
parentrfkill: refactor actions (diff)
downloadkernel-qcow2-util-linux-49f4f7b6c5018c53b84e55f7105a42bfab337249.tar.gz
kernel-qcow2-util-linux-49f4f7b6c5018c53b84e55f7105a42bfab337249.tar.xz
kernel-qcow2-util-linux-49f4f7b6c5018c53b84e55f7105a42bfab337249.zip
rfkill: remove duplicate code
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/rfkill.c')
-rw-r--r--sys-utils/rfkill.c141
1 files changed, 82 insertions, 59 deletions
diff --git a/sys-utils/rfkill.c b/sys-utils/rfkill.c
index 5ffbbf59a..b33f8ea5e 100644
--- a/sys-utils/rfkill.c
+++ b/sys-utils/rfkill.c
@@ -172,20 +172,57 @@ static int string_to_action(const char *str)
return -EINVAL;
}
+static int rfkill_ro_open(int nonblock)
+{
+ int fd;
+
+ fd = open(_PATH_DEV_RFKILL, O_RDONLY);
+ if (fd < 0) {
+ warn(_("cannot open %s"), _PATH_DEV_RFKILL);
+ return -errno;
+ }
+
+ if (nonblock && fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ warn(_("cannot set non-blocking %s"), _PATH_DEV_RFKILL);
+ close(fd);
+ return -errno;
+ }
+
+ return fd;
+}
+
+/* returns: 0 success, 1 read again, < 0 error */
+static int rfkill_read_event(int fd, struct rfkill_event *event)
+{
+ ssize_t len = read(fd, event, sizeof(event));
+
+ if (len < 0) {
+ if (errno == EAGAIN)
+ return 1;
+ warn(_("cannot read %s"), _PATH_DEV_RFKILL);
+ return -errno;
+ }
+
+ if (len < RFKILL_EVENT_SIZE_V1) {
+ warnx(_("wrong size of rfkill event: %zu < %d"), len, RFKILL_EVENT_SIZE_V1);
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int rfkill_event(void)
{
struct rfkill_event event;
struct timeval tv;
char date_buf[ISO_8601_BUFSIZ];
struct pollfd p;
- ssize_t len;
int fd, n;
- fd = open(_PATH_DEV_RFKILL, O_RDONLY);
- if (fd < 0) {
- warn(_("cannot open %s"), _PATH_DEV_RFKILL);
+ fd = rfkill_ro_open(0);
+ if (fd < 0)
return -errno;
- }
memset(&p, 0, sizeof(p));
p.fd = fd;
@@ -193,25 +230,21 @@ static int rfkill_event(void)
/* interrupted by signal only */
while (1) {
+ int rc = 1; /* recover-able error */
+
n = poll(&p, 1, -1);
if (n < 0) {
warn(_("failed to poll %s"), _PATH_DEV_RFKILL);
goto failed;
}
- if (n == 0)
- continue;
-
- len = read(fd, &event, sizeof(event));
- if (len < 0) {
- warn(_("cannot read %s"), _PATH_DEV_RFKILL);
+ if (n)
+ rc = rfkill_read_event(fd, &event);
+ if (rc < 0)
goto failed;
- }
-
- if (len < RFKILL_EVENT_SIZE_V1) {
- warnx(_("wrong size of rfkill event: %zu < %d"), len, RFKILL_EVENT_SIZE_V1);
+ if (rc)
continue;
- }
+
gettimeofday(&tv, NULL);
strtimeval_iso(&tv,
ISO_8601_DATE |
@@ -298,6 +331,30 @@ static struct rfkill_id rfkill_id_to_type(const char *s)
return ret;
}
+static int event_match(struct rfkill_event *event, struct rfkill_id *id)
+{
+ if (event->op != RFKILL_OP_ADD)
+ return 0;
+
+ /* filter out unwanted results */
+ switch (id->result) {
+ case RFKILL_IS_TYPE:
+ if (event->type != id->type)
+ return 0;
+ break;
+ case RFKILL_IS_INDEX:
+ if (event->idx != id->index)
+ return 0;
+ break;
+ case RFKILL_IS_ALL:
+ break;
+ default:
+ abort();
+ }
+
+ return 1;
+}
+
static void fill_table_row(struct libscols_table *tb, struct rfkill_event *event)
{
static struct libscols_line *ln;
@@ -359,13 +416,11 @@ static void rfkill_list_init(struct control *ctrl)
}
}
-
static int rfkill_list_fill(struct control const *ctrl, const char *param)
{
struct rfkill_id id = { .result = RFKILL_IS_ALL };
struct rfkill_event event;
- ssize_t len;
- int fd;
+ int fd, rc = 0;
if (param) {
id = rfkill_id_to_type(param);
@@ -375,53 +430,21 @@ static int rfkill_list_fill(struct control const *ctrl, const char *param)
}
}
- fd = open(_PATH_DEV_RFKILL, O_RDONLY);
- if (fd < 0) {
- warn(_("cannot open %s"), _PATH_DEV_RFKILL);
- return -errno;
- }
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- warn(_("cannot set non-blocking %s"), _PATH_DEV_RFKILL);
- close(fd);
- return -errno;
- }
+ fd = rfkill_ro_open(1);
while (1) {
- len = read(fd, &event, sizeof(event));
- if (len < 0) {
- if (errno != EAGAIN)
- warn(_("cannot read %s"), _PATH_DEV_RFKILL);
+ rc = rfkill_read_event(fd, &event);
+ if (rc < 0)
break;
- }
-
- if (len < RFKILL_EVENT_SIZE_V1) {
- warnx(_("wrong size of rfkill event: %zu < %d"), len, RFKILL_EVENT_SIZE_V1);
- continue;
- }
-
- if (event.op != RFKILL_OP_ADD)
- continue;
-
- /* filter out unwanted results */
- switch (id.result) {
- case RFKILL_IS_TYPE:
- if (event.type != id.type)
- continue;
- break;
- case RFKILL_IS_INDEX:
- if (event.idx != id.index)
- continue;
+ if (rc == 1 && errno == EAGAIN) {
+ rc = 0; /* done */
break;
- case RFKILL_IS_ALL:
- break;
- default:
- abort();
}
- fill_table_row(ctrl->tb, &event);
+ if (rc == 0 && event_match(&event, &id))
+ fill_table_row(ctrl->tb, &event);
}
close(fd);
- return 0;
+ return rc;
}
static void rfkill_list_output(struct control const *ctrl)