Introduction
Introduction Statistics Contact Development Disclaimer Help
Improve tokenization for m- and v-flag parsing - quark - quark web server
git clone git://git.suckless.org/quark
Log
Files
Refs
LICENSE
---
commit 33def953e9d216036ad921ac26052a5b0fa790dc
parent 065394cb64395ed9a6e7cc57e2519ee8f754ce3e
Author: Laslo Hunhold <[email protected]>
Date: Sun, 24 Feb 2019 21:50:39 +0100
Improve tokenization for m- and v-flag parsing
I wasn't happy with the tokenizer for the m- and v-flags, because it
was handling space-separated input and there was no way to have spaces
within the tokens themselves. This is a fine detail, but I didn't want
to impose this restriction where it could be solved (path prefixes or
folder names can very well contain spaces).
Given it's a bit quirky to handle multiple arguments to a single flag
in the command line, especially when parameters are optional, this
alternative wasn't further considered and I instead implemented a
tokenizer that allows escaping spaces with '\'.
While at it, I clarified the manual regarding this point.
Signed-off-by: Laslo Hunhold <[email protected]>
Diffstat:
M main.c | 106 ++++++++++++++++++++++++-----…
M quark.1 | 6 ++++--
2 files changed, 88 insertions(+), 24 deletions(-)
---
diff --git a/main.c b/main.c
@@ -90,6 +90,77 @@ handlesignals(void(*hdl)(int))
sigaction(SIGQUIT, &sa, NULL);
}
+static int
+spacetok(const char *s, char **t, size_t tlen)
+{
+ const char *tok;
+ size_t i, j, toki, spaces;
+
+ /* fill token-array with NULL-pointers */
+ for (i = 0; i < tlen; i++) {
+ t[i] = NULL;
+ }
+ toki = 0;
+
+ /* don't allow NULL string or leading spaces */
+ if (!s || *s == ' ') {
+ return 1;
+ }
+start:
+ /* skip spaces */
+ for (; *s == ' '; s++)
+ ;
+
+ /* don't allow trailing spaces */
+ if (*s == '\0') {
+ goto err;
+ }
+
+ /* consume token */
+ for (tok = s, spaces = 0; ; s++) {
+ if (*s == '\\' && *(s + 1) == ' ') {
+ spaces++;
+ s++;
+ continue;
+ } else if (*s == ' ') {
+ /* end of token */
+ goto token;
+ } else if (*s == '\0') {
+ /* end of string */
+ goto token;
+ }
+ }
+token:
+ if (toki >= tlen) {
+ goto err;
+ }
+ if (!(t[toki] = malloc(s - tok - spaces + 1))) {
+ die("malloc:");
+ }
+ for (i = 0, j = 0; j < s - tok - spaces + 1; i++, j++) {
+ if (tok[i] == '\\' && tok[i + 1] == ' ') {
+ i++;
+ }
+ t[toki][j] = tok[i];
+ }
+ t[toki][s - tok - spaces] = '\0';
+ toki++;
+
+ if (*s == ' ') {
+ s++;
+ goto start;
+ }
+
+ return 0;
+err:
+ for (i = 0; i < tlen; i++) {
+ free(t[i]);
+ t[i] = NULL;
+ }
+
+ return 1;
+}
+
static void
usage(void)
{
@@ -113,7 +184,7 @@ main(int argc, char *argv[])
socklen_t in_sa_len;
int insock, status = 0, infd;
const char *err;
- char *tok;
+ char *tok[4];
/* defaults */
int maxnprocs = 512;
@@ -148,21 +219,16 @@ main(int argc, char *argv[])
s.listdirs = 1;
break;
case 'm':
- if (!(tok = strdup(EARGF(usage())))) {
- die("strdup:");
+ if (spacetok(EARGF(usage()), tok, 3) || !tok[0] || !tok[1]) {
+ usage();
}
if (!(s.map = reallocarray(s.map, ++s.map_len,
sizeof(struct map)))) {
die("reallocarray:");
}
- if (!(s.map[s.map_len - 1].from = strtok(tok, " ")) ||
- !(s.map[s.map_len - 1].to = strtok(NULL, " "))) {
- usage();
- }
- s.map[s.map_len - 1].chost = strtok(NULL, " ");
- if (strtok(NULL, "")) {
- usage();
- }
+ s.map[s.map_len - 1].from = tok[0];
+ s.map[s.map_len - 1].to = tok[1];
+ s.map[s.map_len - 1].chost = tok[2];
break;
case 'n':
maxnprocs = strtonum(EARGF(usage()), 1, INT_MAX, &err);
@@ -180,22 +246,18 @@ main(int argc, char *argv[])
user = EARGF(usage());
break;
case 'v':
- if (!(tok = strdup(EARGF(usage())))) {
- die("strdup:");
+ if (spacetok(EARGF(usage()), tok, 4) || !tok[0] || !tok[1] ||
+ !tok[2]) {
+ usage();
}
if (!(s.vhost = reallocarray(s.vhost, ++s.vhost_len,
sizeof(struct vhost)))) {
die("reallocarray:");
}
- if (!(s.vhost[s.vhost_len - 1].chost = strtok(tok, " ")) ||
- !(s.vhost[s.vhost_len - 1].regex = strtok(NULL, " ")) ||
- !(s.vhost[s.vhost_len - 1].dir = strtok(NULL, " "))) {
- usage();
- }
- s.vhost[s.vhost_len - 1].prefix = strtok(NULL, " ");
- if (strtok(NULL, "")) {
- usage();
- }
+ s.vhost[s.vhost_len - 1].chost = tok[0];
+ s.vhost[s.vhost_len - 1].regex = tok[1];
+ s.vhost[s.vhost_len - 1].dir = tok[2];
+ s.vhost[s.vhost_len - 1].prefix = tok[3];
break;
default:
usage();
diff --git a/quark.1 b/quark.1
@@ -58,7 +58,8 @@ Add the target prefix mapping rule specified by
.Ar map ,
which has the form
.Qq Pa from to [chost] ,
-where each element is separated with whitespace.
+where each element is separated with spaces (0x20) that can be
+escaped with '\\'.
.Pp
The prefix
.Pa from
@@ -96,7 +97,8 @@ Add the virtual host specified by
.Ar vhost ,
which has the form
.Qq Pa chost regex dir [prefix] ,
-where each element is separated with whitespace.
+where each element is separated with spaces (0x20) that can be
+escaped with '\\'.
.Pp
A request matching the virtual host regular expression
.Pa regex
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.