mirror of
https://github.com/systemd/systemd.git
synced 2024-11-06 16:59:03 +03:00
util: add shell_maybe_quote() call for preparing a string for shell cmdline inclusion
If necessary the passed string is enclosed in "", and all special characters escapes. This also ports over usage in bus-util.c and job.c to use this, instead of a incorrect local implementation that forgets to properly escape.
This commit is contained in:
parent
ab51b943d4
commit
019c7fba75
@ -674,15 +674,13 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
|
||||
break;
|
||||
|
||||
case JOB_FAILED: {
|
||||
bool quotes;
|
||||
_cleanup_free_ char *quoted = NULL;
|
||||
|
||||
quotes = chars_intersect(u->id, SHELL_NEED_QUOTES);
|
||||
quoted = shell_maybe_quote(u->id);
|
||||
|
||||
manager_flip_auto_status(u->manager, true);
|
||||
unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
|
||||
manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL,
|
||||
"See \"systemctl status %s%s%s\" for details.",
|
||||
quotes ? "'" : "", u->id, quotes ? "'" : "");
|
||||
manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1735,16 +1735,15 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) {
|
||||
else if (streq(d->result, "unsupported"))
|
||||
log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
|
||||
else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
|
||||
if (d->name) {
|
||||
bool quotes;
|
||||
_cleanup_free_ char *quoted = NULL;
|
||||
|
||||
quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
|
||||
if (d->name)
|
||||
quoted = shell_maybe_quote(d->name);
|
||||
|
||||
log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
|
||||
d->name,
|
||||
quotes ? "'" : "", d->name, quotes ? "'" : "");
|
||||
} else
|
||||
log_error("Job failed. See \"journalctl -xe\" for details.");
|
||||
if (quoted)
|
||||
log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xe' for details.", d->name, quoted);
|
||||
else
|
||||
log_error("Job failed. See 'journalctl -xe' for details.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1332,7 +1332,8 @@ char *cescape(const char *s) {
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Does C style string escaping. */
|
||||
/* Does C style string escaping. May be be reversed with
|
||||
* cunescape(). */
|
||||
|
||||
r = new(char, strlen(s)*4 + 1);
|
||||
if (!r)
|
||||
@ -1542,7 +1543,7 @@ char *xescape(const char *s, const char *bad) {
|
||||
|
||||
/* Escapes all chars in bad, in addition to \ and all special
|
||||
* chars, in \xFF style escaping. May be reversed with
|
||||
* cunescape. */
|
||||
* cunescape(). */
|
||||
|
||||
r = new(char, strlen(s) * 4 + 1);
|
||||
if (!r)
|
||||
@ -8035,3 +8036,43 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *shell_maybe_quote(const char *s) {
|
||||
const char *p;
|
||||
char *r, *t;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Encloses a string in double quotes if necessary to make it
|
||||
* OK as shell string. */
|
||||
|
||||
for (p = s; *p; p++)
|
||||
if (*p <= ' ' ||
|
||||
*p >= 127 ||
|
||||
strchr(SHELL_NEED_QUOTES, *p))
|
||||
break;
|
||||
|
||||
if (!*p)
|
||||
return strdup(s);
|
||||
|
||||
r = new(char, 1+strlen(s)*2+1+1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
t = r;
|
||||
*(t++) = '"';
|
||||
t = mempcpy(t, s, p - s);
|
||||
|
||||
for (; *p; p++) {
|
||||
|
||||
if (strchr(SHELL_NEED_ESCAPE, *p))
|
||||
*(t++) = '\\';
|
||||
|
||||
*(t++) = *p;
|
||||
}
|
||||
|
||||
*(t++)= '"';
|
||||
*t = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1090,3 +1090,5 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility);
|
||||
void cmsg_close_all(struct msghdr *mh);
|
||||
|
||||
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
|
||||
|
||||
char *shell_maybe_quote(const char *s);
|
||||
|
@ -1542,6 +1542,24 @@ static void test_sparse_write(void) {
|
||||
test_sparse_write_one(fd, test_e, sizeof(test_e));
|
||||
}
|
||||
|
||||
static void test_shell_maybe_quote_one(const char *s, const char *expected) {
|
||||
_cleanup_free_ char *r;
|
||||
|
||||
assert_se(r = shell_maybe_quote(s));
|
||||
assert_se(streq(r, expected));
|
||||
}
|
||||
|
||||
static void test_shell_maybe_quote(void) {
|
||||
|
||||
test_shell_maybe_quote_one("", "");
|
||||
test_shell_maybe_quote_one("\\", "\"\\\\\"");
|
||||
test_shell_maybe_quote_one("\"", "\"\\\"\"");
|
||||
test_shell_maybe_quote_one("foobar", "foobar");
|
||||
test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
|
||||
test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
|
||||
test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
@ -1619,6 +1637,7 @@ int main(int argc, char *argv[]) {
|
||||
test_same_fd();
|
||||
test_uid_ptr();
|
||||
test_sparse_write();
|
||||
test_shell_maybe_quote();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user