#include "timeutils.h"
#include "widechar.h"
#include "xalloc.h"
+#include "all-io.h"
/*
ACT_EVENT,
ACT_BLOCK,
ACT_UNBLOCK,
+ ACT_TOGGLE,
ACT_LIST_OLD
};
[ACT_HELP] = "help",
[ACT_EVENT] = "event",
[ACT_BLOCK] = "block",
- [ACT_UNBLOCK] = "unblock"
+ [ACT_UNBLOCK] = "unblock",
+ [ACT_TOGGLE] = "toggle"
};
/* column IDs */
return -EINVAL;
}
-static int rfkill_ro_open(int nonblock)
+static int rfkill_open(int rdonly, int nonblock)
{
int fd;
- fd = open(_PATH_DEV_RFKILL, O_RDONLY);
+ fd = open(_PATH_DEV_RFKILL, rdonly ? O_RDONLY : O_RDWR);
if (fd < 0) {
warn(_("cannot open %s"), _PATH_DEV_RFKILL);
return -errno;
struct pollfd p;
int fd, n;
- fd = rfkill_ro_open(0);
+ fd = rfkill_open(1, 0);
if (fd < 0)
- return -errno;
+ return fd;
memset(&p, 0, sizeof(p));
p.fd = fd;
}
}
- fd = rfkill_ro_open(1);
+ fd = rfkill_open(1, 1);
if (fd < 0)
- return -errno;
+ return fd;
while (1) {
rc = rfkill_read_event(fd, &event);
}
}
- fd = rfkill_ro_open(1);
+ fd = rfkill_open(1, 1);
if (fd < 0)
- return -errno;
+ return fd;
while (1) {
rc = rfkill_read_event(fd, &event);
scols_unref_table(ctrl->tb);
}
-static int rfkill_block(uint8_t block, const char *param)
+static int __rfkill_block(int fd, struct rfkill_id *id, uint8_t block, const char *param)
{
- struct rfkill_id id;
struct rfkill_event event = {
.op = RFKILL_OP_CHANGE_ALL,
.soft = block,
0
};
- ssize_t len;
- int fd;
char *message = NULL;
- id = rfkill_id_to_type(param);
-
- switch (id.result) {
+ switch (id->result) {
case RFKILL_IS_INVALID:
warnx(_("invalid identifier: %s"), param);
return -1;
case RFKILL_IS_TYPE:
- event.type = id.type;
+ event.type = id->type;
xasprintf(&message, "type %s", param);
break;
case RFKILL_IS_INDEX:
event.op = RFKILL_OP_CHANGE;
- event.idx = id.index;
- xasprintf(&message, "id %d", id.index);
+ event.idx = id->index;
+ xasprintf(&message, "id %d", id->index);
break;
case RFKILL_IS_ALL:
message = xstrdup("all");
abort();
}
- fd = open(_PATH_DEV_RFKILL, O_RDWR);
- if (fd < 0) {
- warn(_("cannot open %s"), _PATH_DEV_RFKILL);
- free(message);
- return -errno;
- }
-
- len = write(fd, &event, sizeof(event));
- if (len < 0)
+ if (write_all(fd, &event, sizeof(event)) != 0)
warn(_("write failed: %s"), _PATH_DEV_RFKILL);
else {
openlog("rfkill", 0, LOG_USER);
closelog();
}
free(message);
+ return 0;
+}
+
+static int rfkill_block(uint8_t block, const char *param)
+{
+ struct rfkill_id id;
+ int fd;
+
+ id = rfkill_id_to_type(param);
+ if (id.result == RFKILL_IS_INVALID) {
+ warnx(_("invalid identifier: %s"), param);
+ return -EINVAL;
+ }
+
+ fd = rfkill_open(0, 0);
+ if (fd < 0)
+ return fd;
+
+ __rfkill_block(fd, &id, block, param);
+
return close(fd);
}
+static int rfkill_toggle(const char *param)
+{
+ struct rfkill_id id = { .result = RFKILL_IS_ALL };
+ struct rfkill_event event;
+ int fd, rc = 0;
+
+ id = rfkill_id_to_type(param);
+ if (id.result == RFKILL_IS_INVALID) {
+ warnx(_("invalid identifier: %s"), param);
+ return -EINVAL;
+ }
+
+ fd = rfkill_open(0, 1);
+ if (fd < 0)
+ return fd;
+
+ while (1) {
+ rc = rfkill_read_event(fd, &event);
+ if (rc < 0)
+ break;
+ if (rc == 1 && errno == EAGAIN) {
+ rc = 0; /* done */
+ break;
+ }
+ if (rc == 0 && event_match(&event, &id))
+ __rfkill_block(fd, &id, event.soft ? 0 : 1, param);
+ }
+
+ close(fd);
+ return rc;
+}
+
+
static void __attribute__((__noreturn__)) usage(void)
{
size_t i;
fputs(_(" list [identifier]\n"), stdout);
fputs(_(" block identifier\n"), stdout);
fputs(_(" unblock identifier\n"), stdout);
+ fputs(_(" toggle identifier\n"), stdout);
fprintf(stdout, USAGE_MAN_TAIL("rfkill(8)"));
exit(EXIT_SUCCESS);
/*
* For backward compatibility we use old output format if
- * "list" explicitly specified and--output not defined.
+ * "list" explicitly specified and --output not defined.
*/
if (!outarg && act == ACT_LIST)
act = ACT_LIST_OLD;
argc--;
}
break;
+
+ case ACT_TOGGLE:
+ while (argc) {
+ ret |= rfkill_toggle(*argv);
+ argv++;
+ argc--;
+ }
+ break;
}
return ret ? EXIT_FAILURE : EXIT_SUCCESS;