aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/bus-broadcast.16
-rw-r--r--doc/bus-chgrp.11
-rw-r--r--doc/bus-chmod.11
-rw-r--r--doc/bus-chown.11
-rw-r--r--doc/bus-create.16
-rw-r--r--doc/bus-listen.13
-rw-r--r--doc/bus-remove.11
-rw-r--r--doc/bus-wait.11
-rw-r--r--src/cmdline.c119
9 files changed, 98 insertions, 41 deletions
diff --git a/doc/bus-broadcast.1 b/doc/bus-broadcast.1
index d80c6d2..5a4a7a3 100644
--- a/doc/bus-broadcast.1
+++ b/doc/bus-broadcast.1
@@ -3,10 +3,16 @@
bus broadcast - Broadcast a message on a bus
.SH SYNOPSIS
.B bus broadcast
+.IR [options]
+[--]
.IR pathname
.IR message
.SH DESCRIPTION
Broadcast \fImessage\fP on the bus associated with \fIpathname\fP.
+.SH OPTIONS
+.TP
+.B \-n
+Fail if another process is attempting to broadcast on the bus.
.SH EXIT STATUS
.TP
0
diff --git a/doc/bus-chgrp.1 b/doc/bus-chgrp.1
index cb59916..49f5642 100644
--- a/doc/bus-chgrp.1
+++ b/doc/bus-chgrp.1
@@ -3,6 +3,7 @@
bus chgrp - Change group ownership of a bus
.SH SYNOPSIS
.B bus chgrp
+[--]
.IR group
.IR pathname
.SH DESCRIPTION
diff --git a/doc/bus-chmod.1 b/doc/bus-chmod.1
index f50688c..24cdac9 100644
--- a/doc/bus-chmod.1
+++ b/doc/bus-chmod.1
@@ -3,6 +3,7 @@
bus chmod - Change permissions on a bus
.SH SYNOPSIS
.B bus chmod
+[--]
.IR permissions
.IR pathname
.SH DESCRIPTION
diff --git a/doc/bus-chown.1 b/doc/bus-chown.1
index 64aa7d2..a9c09ff 100644
--- a/doc/bus-chown.1
+++ b/doc/bus-chown.1
@@ -3,6 +3,7 @@
bus chown - Change ownership of a bus
.SH SYNOPSIS
.B bus chown
+[--]
.IR owner[:group]
.IR pathname
.SH DESCRIPTION
diff --git a/doc/bus-create.1 b/doc/bus-create.1
index 8282413..f50ad97 100644
--- a/doc/bus-create.1
+++ b/doc/bus-create.1
@@ -3,11 +3,17 @@
bus create - Create a bus
.SH SYNOPSIS
.B bus create
+.IR [options]
+[--]
.IR [pathname]
.SH DESCRIPTION
Create a bus with an associated \fIpathname\fP. If \fIpathname\fP, a
random pathname in \fI$XDG_RUNTIME_DIR/bus\fP will be created and
printed to stdout.
+.SH OPTIONS
+.TP
+.B \-x
+Fail if the \fIpathname\fP already exists.
.SH EXIT STATUS
.TP
0
diff --git a/doc/bus-listen.1 b/doc/bus-listen.1
index 0d5b9ba..0f56398 100644
--- a/doc/bus-listen.1
+++ b/doc/bus-listen.1
@@ -2,7 +2,8 @@
.SH NAME
bus listen - Listen for new messages on a bus
.SH SYNOPSIS
-.B bus wait
+.B bus listen
+[--]
.IR pathname
.IR command
.SH DESCRIPTION
diff --git a/doc/bus-remove.1 b/doc/bus-remove.1
index 1979629..1b14d50 100644
--- a/doc/bus-remove.1
+++ b/doc/bus-remove.1
@@ -3,6 +3,7 @@
bus remove - Remove a bus
.SH SYNOPSIS
.B bus remove
+[--]
.IR pathname
.SH DESCRIPTION
Remove the bus associated with \fIpathname\fP.
diff --git a/doc/bus-wait.1 b/doc/bus-wait.1
index 5fec137..c9add51 100644
--- a/doc/bus-wait.1
+++ b/doc/bus-wait.1
@@ -3,6 +3,7 @@
bus wait - Listen for a new message on a bus
.SH SYNOPSIS
.B bus wait
+[--]
.IR pathname
.IR command
.SH DESCRIPTION
diff --git a/src/cmdline.c b/src/cmdline.c
index 69adae2..97da729 100644
--- a/src/cmdline.c
+++ b/src/cmdline.c
@@ -292,14 +292,14 @@ parse_owner(char *str, uid_t *uid, gid_t *gid)
*
* @param argc The number of elements in `argv`
* @param argv The command. Valid commands:
- * <argv0> create [<path>] # create a bus
- * <argv0> remove <path> # remove a bus
- * <argv0> listen <path> <command> # listen for new messages
- * <argv0> wait <path> <command> # listen for one new message
- * <argv0> broadcast <path> <message> # broadcast a message
- * <argv0> chmod <mode> <path> # change permissions
- * <argv0> chown <owner>[:<group>] <path> # change ownership
- * <argv0> chgrp <group> <path> # change group
+ * <argv0> create [-x] [--] [<path>] # create a bus
+ * <argv0> remove [--] <path> # remove a bus
+ * <argv0> listen [--] <path> <command> # listen for new messages
+ * <argv0> wait [--] <path> <command> # listen for one new message
+ * <argv0> broadcast [-n] [--] <path> <message> # broadcast a message
+ * <argv0> chmod [--] <mode> <path> # change permissions
+ * <argv0> chown [--] <owner>[:<group>] <path> # change ownership
+ * <argv0> chgrp [--] <group> <path> # change group
* <command> will be spawned with $arg set to the message
* @return 0 on sucess, 1 on error, 2 on invalid command
*/
@@ -312,69 +312,108 @@ main(int argc, char *argv[])
uid_t uid;
gid_t gid;
mode_t mode_andnot, mode_or;
+ int opt_x = 0, opt_n = 0;
+ const char *arg;
+ char **nonoptv = alloca(argc * sizeof(char*));
+ int nonoptc = 0;
+
+ argv0 = *argv++;
+ argc--;
+
+ /* Parse arguments. */
+ while (argc) {
+ if (!strcmp(*argv, "--")) {
+ argv++;
+ argc--;
+ break;
+ } else if (**argv == '-') {
+ arg = *argv++;
+ argc--;
+ for (arg++; *arg; arg++) {
+ if (*arg == 'x')
+ opt_x = 1;
+ else if (*arg == 'n')
+ opt_n = 1;
+ else
+ return -2;
+ }
+ } else {
+ *nonoptv++ = *argv++;
+ nonoptc++;
+ argc--;
+ }
+ }
+ while (argc) {
+ *nonoptv++ = *argv++;
+ nonoptc++;
+ argc--;
+ }
+ nonoptv -= nonoptc;
- argv0 = *argv;
+ /* Check options. */
+ if (opt_x && strcmp(nonoptv[0], "create") && (nonoptc != 2))
+ return 2;
+ if (opt_n && strcmp(nonoptv[0], "broadcast") && (nonoptc != 3))
+ return 2;
/* Create a new bus with selected name. */
- if ((argc == 3) && !strcmp(argv[1], "create")) {
- t(bus_create(argv[2], 0, NULL));
- /* TODO add -x */
+ if ((nonoptc == 2) && !strcmp(nonoptv[0], "create")) {
+ t(bus_create(nonoptv[1], opt_x * BUS_EXCL, NULL));
/* Create a new bus with random name. */
- } else if ((argc == 2) && !strcmp(argv[1], "create")) {
+ } else if ((nonoptc == 1) && !strcmp(nonoptv[0], "create")) {
t(bus_create(NULL, 0, &file));
printf("%s\n", file);
free(file);
/* Remove a bus. */
- } else if ((argc == 3) && !strcmp(argv[1], "remove")) {
- t(bus_unlink(argv[2]));
+ } else if ((nonoptc == 2) && !strcmp(nonoptv[0], "remove")) {
+ t(bus_unlink(nonoptv[1]));
/* Listen on a bus in a loop. */
- } else if ((argc == 4) && !strcmp(argv[1], "listen")) {
- command = argv[3];
- t(bus_open(&bus, argv[2], BUS_RDONLY));
+ } else if ((nonoptc == 3) && !strcmp(nonoptv[0], "listen")) {
+ command = nonoptv[2];
+ t(bus_open(&bus, nonoptv[1], BUS_RDONLY));
t(bus_read(&bus, spawn_continue, NULL));
t(bus_close(&bus));
/* Listen on a bus for one message. */
- } else if ((argc == 4) && !strcmp(argv[1], "wait")) {
- command = argv[3];
- t(bus_open(&bus, argv[2], BUS_RDONLY));
+ } else if ((nonoptc == 3) && !strcmp(nonoptv[0], "wait")) {
+ command = nonoptv[2];
+ t(bus_open(&bus, nonoptv[1], BUS_RDONLY));
t(bus_read(&bus, spawn_break, NULL));
t(bus_close(&bus));
/* Broadcast a message on a bus. */
- } else if ((argc == 4) && !strcmp(argv[1], "broadcast")) {
- t(bus_open(&bus, argv[2], BUS_WRONLY));
- t(bus_write(&bus, argv[3], 0));
+ } else if ((nonoptc == 3) && !strcmp(nonoptv[0], "broadcast")) {
+ t(bus_open(&bus, nonoptv[1], BUS_WRONLY));
+ t(bus_write(&bus, nonoptv[2], opt_n * BUS_NOWAIT));
t(bus_close(&bus));
- /* TODO add -n */
/* Change permissions. */
- } else if ((argc == 4) && !strcmp(argv[1], "chmod")) {
- t(parse_mode(argv[2], &mode_andnot, &mode_or));
- t(stat(argv[3], &attr));
+ } else if ((nonoptc == 3) && !strcmp(nonoptv[0], "chmod")) {
+ t(parse_mode(nonoptv[1], &mode_andnot, &mode_or));
+ t(stat(nonoptv[2], &attr));
attr.st_mode &= ~mode_andnot;
attr.st_mode |= mode_or;
- t(bus_chmod(argv[3], attr.st_mode));
+ t(bus_chmod(nonoptv[2], attr.st_mode));
/* Change ownership. */
- } else if ((argc == 4) && !strcmp(argv[1], "chown")) {
- if (strchr(argv[2], ':')) {
- t(parse_owner(argv[2], &uid, &gid));
- t(bus_chown(argv[3], uid, gid));
+ } else if ((nonoptc == 3) && !strcmp(nonoptv[0], "chown")) {
+ if (strchr(nonoptv[1], ':')) {
+ t(parse_owner(nonoptv[1], &uid, &gid));
+ t(bus_chown(nonoptv[2], uid, gid));
} else {
- t(parse_owner(argv[2], &uid, NULL));
- t(stat(argv[3], &attr));
- t(bus_chown(argv[3], uid, attr.st_gid));
+ t(parse_owner(nonoptv[1], &uid, NULL));
+ t(stat(nonoptv[2], &attr));
+ t(bus_chown(nonoptv[2], uid, attr.st_gid));
}
/* Change group. */
- } else if ((argc == 4) && !strcmp(argv[1], "chgrp")) {
- t(parse_owner(argv[2], NULL, &gid));
- t(stat(argv[3], &attr));
- t(bus_chown(argv[3], attr.st_uid, gid));
+ } else if ((nonoptc == 3) && !strcmp(nonoptv[0], "chgrp")) {
+ t(parse_owner(nonoptv[1], NULL, &gid));
+ t(stat(nonoptv[2], &attr));
+ t(bus_chown(nonoptv[2], attr.st_uid, gid));
} else
return 2;