diff options
-rw-r--r-- | doc/bus-broadcast.1 | 6 | ||||
-rw-r--r-- | doc/bus-chgrp.1 | 1 | ||||
-rw-r--r-- | doc/bus-chmod.1 | 1 | ||||
-rw-r--r-- | doc/bus-chown.1 | 1 | ||||
-rw-r--r-- | doc/bus-create.1 | 6 | ||||
-rw-r--r-- | doc/bus-listen.1 | 3 | ||||
-rw-r--r-- | doc/bus-remove.1 | 1 | ||||
-rw-r--r-- | doc/bus-wait.1 | 1 | ||||
-rw-r--r-- | src/cmdline.c | 119 |
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; |