From aae4b4d3585b9f944d7dbd3c9e5ba0006c55e457 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 8 Jun 2021 06:54:40 +0000 Subject: upstream: Allow argv_split() to optionally terminate tokenisation when it encounters an unquoted comment. Add some additional utility function for working with argument vectors, since we'll be switching to using them to parse ssh/sshd_config shortly. ok markus@ as part of a larger diff; tested in snaps OpenBSD-Commit-ID: fd9c108cef2f713f24e3bc5848861d221bb3a1ac --- misc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) (limited to 'misc.c') diff --git a/misc.c b/misc.c index 78fb1e00..3c9ea067 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.165 2021/06/04 05:02:40 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.166 2021/06/08 06:54:40 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. @@ -85,6 +85,20 @@ chop(char *s) } +/* remove whitespace from end of string */ +void +rtrim(char *s) +{ + size_t i; + + if ((i = strlen(s)) == 0) + return; + for (i--; i > 0; i--) { + if (isspace((int)s[i])) + s[i] = '\0'; + } +} + /* set/unset filedescriptor to non-blocking */ int set_nonblock(int fd) @@ -1912,14 +1926,13 @@ daemonized(void) return 1; } - /* * Splits 's' into an argument vector. Handles quoted string and basic * escape characters (\\, \", \'). Caller must free the argument vector * and its members. */ int -argv_split(const char *s, int *argcp, char ***argvp) +argv_split(const char *s, int *argcp, char ***argvp, int terminate_on_comment) { int r = SSH_ERR_INTERNAL_ERROR; int argc = 0, quote, i, j; @@ -1932,7 +1945,8 @@ argv_split(const char *s, int *argcp, char ***argvp) /* Skip leading whitespace */ if (s[i] == ' ' || s[i] == '\t') continue; - + if (terminate_on_comment && s[i] == '#') + break; /* Start of a token */ quote = 0; @@ -1945,7 +1959,8 @@ argv_split(const char *s, int *argcp, char ***argvp) if (s[i] == '\\') { if (s[i + 1] == '\'' || s[i + 1] == '\"' || - s[i + 1] == '\\') { + s[i + 1] == '\\' || + (quote == 0 && s[i + 1] == ' ')) { i++; /* Skip '\' */ arg[j++] = s[i]; } else { @@ -2039,6 +2054,36 @@ argv_assemble(int argc, char **argv) return ret; } +char * +argv_next(int *argcp, char ***argvp) +{ + char *ret = (*argvp)[0]; + + if (*argcp > 0 && ret != NULL) { + (*argcp)--; + (*argvp)++; + } + return ret; +} + +void +argv_consume(int *argcp) +{ + *argcp = 0; +} + +void +argv_free(char **av, int ac) +{ + int i; + + if (av == NULL) + return; + for (i = 0; i < ac; i++) + free(av[i]); + free(av); +} + /* Returns 0 if pid exited cleanly, non-zero otherwise */ int exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) -- cgit v1.2.1