diff options
Diffstat (limited to 'src/shared')
| -rw-r--r-- | src/shared/acl-util.c | 8 | ||||
| -rw-r--r-- | src/shared/ask-password-api.c | 4 | ||||
| -rw-r--r-- | src/shared/ask-password-api.h | 1 | ||||
| -rw-r--r-- | src/shared/bus-unit-util.c | 2 | ||||
| -rw-r--r-- | src/shared/bus-util.c | 8 | ||||
| -rw-r--r-- | src/shared/conf-parser.c | 4 | ||||
| -rw-r--r-- | src/shared/dissect-image.c | 4 | ||||
| -rw-r--r-- | src/shared/efivars.c | 134 | ||||
| -rw-r--r-- | src/shared/install.c | 6 | ||||
| -rw-r--r-- | src/shared/journal-importer.c | 5 | ||||
| -rw-r--r-- | src/shared/journal-importer.h | 3 | ||||
| -rw-r--r-- | src/shared/json.c | 7 | ||||
| -rw-r--r-- | src/shared/json.h | 3 | ||||
| -rw-r--r-- | src/shared/lockfile-util.c | 1 | ||||
| -rw-r--r-- | src/shared/logs-show.c | 4 | ||||
| -rw-r--r-- | src/shared/loop-util.c | 7 | ||||
| -rw-r--r-- | src/shared/pager.c | 4 | ||||
| -rw-r--r-- | src/shared/seccomp-util.c | 1 | ||||
| -rw-r--r-- | src/shared/switch-root.c | 2 | ||||
| -rw-r--r-- | src/shared/xml.c | 2 |
20 files changed, 116 insertions, 94 deletions
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index 6f0657174c..9633514513 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -220,10 +220,10 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want char *p; p = STARTSWITH_SET(*entry, "default:", "d:"); - if (!p) - p = *entry; - - r = strv_push(&d, p); + if (p) + r = strv_push(&d, p); + else + r = strv_push(&a, *entry); if (r < 0) return r; } diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 246e27a135..072bf72c56 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -156,7 +156,7 @@ static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, c return 0; } -int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) { +static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) { key_serial_t serial; int r; @@ -341,7 +341,7 @@ int ask_password_tty( goto finish; } - if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) { + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyname) { (void) flush_fd(notify); r = ask_password_keyring(keyname, flags, ret); diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 2d84ba6b04..15762b9cde 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -17,5 +17,4 @@ typedef enum AskPasswordFlags { int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); -int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret); int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index dce8646f37..9a8051d063 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -118,7 +118,7 @@ DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode); DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou); DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64); -static inline int bus_append_string(sd_bus_message *m, const char *field, const char *eq) { +static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) { int r; r = sd_bus_message_append(m, "(sv)", field, "s", eq); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 976643e4ce..cbcf698e96 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -559,7 +559,7 @@ int bus_check_peercred(sd_bus *c) { } int bus_connect_system_systemd(sd_bus **_bus) { - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; int r; assert(_bus); @@ -592,7 +592,7 @@ int bus_connect_system_systemd(sd_bus **_bus) { } int bus_connect_user_systemd(sd_bus **_bus) { - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *ee = NULL; const char *e; int r; @@ -1279,7 +1279,7 @@ int bus_map_all_properties( } int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) { - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; int r; assert(transport >= 0); @@ -1666,7 +1666,7 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) { } int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) { - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; const char *e; int r; diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 8fe177990a..b80c147807 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -137,7 +137,7 @@ static int next_assignment( /* Warn about unknown non-extension fields. */ if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-")) - log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s'", lvalue, section); + log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown lvalue '%s' in section '%s', ignoring", lvalue, section); return 0; } @@ -321,7 +321,7 @@ int config_parse(const char *unit, return r; } - if (strchr(COMMENTS, *buf)) + if (strchr(COMMENTS, *skip_leading_chars(buf, WHITESPACE))) continue; l = buf; diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 3a46faf769..d340487025 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1178,7 +1178,6 @@ int dissected_image_decrypt_interactively( #if HAVE_LIBCRYPTSETUP static int deferred_remove(DecryptedPartition *p) { - struct dm_ioctl dm = { .version = { DM_VERSION_MAJOR, @@ -1199,6 +1198,9 @@ static int deferred_remove(DecryptedPartition *p) { if (fd < 0) return -errno; + if (strlen(p->name) > sizeof(dm.name)) + return -ENAMETOOLONG; + strncpy(dm.name, p->name, sizeof(dm.name)); if (ioctl(fd, DM_DEV_REMOVE, &dm)) diff --git a/src/shared/efivars.c b/src/shared/efivars.c index cb9e13c15f..26f905bfaa 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -40,11 +40,17 @@ #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 -struct boot_option { - uint32_t attr; - uint16_t path_len; - uint16_t title[]; -} _packed_; +#define boot_option__contents { \ + uint32_t attr; \ + uint16_t path_len; \ + uint16_t title[]; \ + } + +struct boot_option boot_option__contents; +struct boot_option__packed boot_option__contents _packed_; +assert_cc(offsetof(struct boot_option, title) == offsetof(struct boot_option__packed, title)); +/* sizeof(struct boot_option) != sizeof(struct boot_option__packed), so + * the *size* of the structure should not be used anywhere below. */ struct drive_path { uint32_t part_nr; @@ -55,15 +61,19 @@ struct drive_path { uint8_t signature_type; } _packed_; -struct device_path { - uint8_t type; - uint8_t sub_type; - uint16_t length; - union { - uint16_t path[0]; - struct drive_path drive; - }; -} _packed_; +#define device_path__contents { \ + uint8_t type; \ + uint8_t sub_type; \ + uint16_t length; \ + union { \ + uint16_t path[0]; \ + struct drive_path drive; \ + }; \ + } + +struct device_path device_path__contents; +struct device_path__packed device_path__contents _packed_; +assert_cc(sizeof(struct device_path) == sizeof(struct device_path__packed)); bool is_efi_boot(void) { if (detect_container() > 0) @@ -354,32 +364,46 @@ int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *v) return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t)); } -static size_t utf16_size(const uint16_t *s) { +static ssize_t utf16_size(const uint16_t *s, size_t buf_len_bytes) { size_t l = 0; - while (s[l] > 0) + /* Returns the size of the string in bytes without the terminating two zero bytes */ + + if (buf_len_bytes % sizeof(uint16_t) != 0) + return -EINVAL; + + while (l < buf_len_bytes / sizeof(uint16_t)) { + if (s[l] == 0) + return (l + 1) * sizeof(uint16_t); l++; + } - return (l+1) * sizeof(uint16_t); + return -EINVAL; /* The terminator was not found */ } +struct guid { + uint32_t u1; + uint16_t u2; + uint16_t u3; + uint8_t u4[8]; +} _packed_; + static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) { - struct uuid { - uint32_t u1; - uint16_t u2; - uint16_t u3; - uint8_t u4[8]; - } _packed_; - const struct uuid *uuid = guid; - - id128->bytes[0] = (uuid->u1 >> 24) & 0xff; - id128->bytes[1] = (uuid->u1 >> 16) & 0xff; - id128->bytes[2] = (uuid->u1 >> 8) & 0xff; - id128->bytes[3] = (uuid->u1) & 0xff; - id128->bytes[4] = (uuid->u2 >> 8) & 0xff; - id128->bytes[5] = (uuid->u2) & 0xff; - id128->bytes[6] = (uuid->u3 >> 8) & 0xff; - id128->bytes[7] = (uuid->u3) & 0xff; + uint32_t u1; + uint16_t u2, u3; + const struct guid *uuid = guid; + + memcpy(&u1, &uuid->u1, sizeof(uint32_t)); + id128->bytes[0] = (u1 >> 24) & 0xff; + id128->bytes[1] = (u1 >> 16) & 0xff; + id128->bytes[2] = (u1 >> 8) & 0xff; + id128->bytes[3] = u1 & 0xff; + memcpy(&u2, &uuid->u2, sizeof(uint16_t)); + id128->bytes[4] = (u2 >> 8) & 0xff; + id128->bytes[5] = u2 & 0xff; + memcpy(&u3, &uuid->u3, sizeof(uint16_t)); + id128->bytes[6] = (u3 >> 8) & 0xff; + id128->bytes[7] = u3 & 0xff; memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4)); } @@ -394,7 +418,7 @@ int efi_get_boot_option( _cleanup_free_ uint8_t *buf = NULL; size_t l; struct boot_option *header; - size_t title_size; + ssize_t title_size; _cleanup_free_ char *s = NULL, *p = NULL; sd_id128_t p_uuid = SD_ID128_NULL; int r; @@ -406,13 +430,13 @@ int efi_get_boot_option( r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l); if (r < 0) return r; - if (l < sizeof(struct boot_option)) + if (l < offsetof(struct boot_option, title)) return -ENOENT; header = (struct boot_option *)buf; - title_size = utf16_size(header->title); - if (title_size > l - offsetof(struct boot_option, title)) - return -EINVAL; + title_size = utf16_size(header->title, l - offsetof(struct boot_option, title)); + if (title_size < 0) + return title_size; if (title) { s = utf16_to_utf8(header->title, title_size); @@ -494,20 +518,14 @@ static void to_utf16(uint16_t *dest, const char *src) { dest[i] = '\0'; } -struct guid { - uint32_t u1; - uint16_t u2; - uint16_t u3; - uint8_t u4[8]; -} _packed_; - static void id128_to_efi_guid(sd_id128_t id, void *guid) { - struct guid *uuid = guid; - - uuid->u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3]; - uuid->u2 = id.bytes[4] << 8 | id.bytes[5]; - uuid->u3 = id.bytes[6] << 8 | id.bytes[7]; - memcpy(uuid->u4, id.bytes+8, sizeof(uuid->u4)); + struct guid uuid = { + .u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3], + .u2 = id.bytes[4] << 8 | id.bytes[5], + .u3 = id.bytes[6] << 8 | id.bytes[7], + }; + memcpy(uuid.u4, id.bytes+8, sizeof(uuid.u4)); + memcpy(guid, &uuid, sizeof(uuid)); } static uint16_t *tilt_slashes(uint16_t *s) { @@ -541,7 +559,7 @@ int efi_add_boot_option( title_len = (strlen(title)+1) * 2; path_len = (strlen(path)+1) * 2; - buf = malloc0(sizeof(struct boot_option) + title_len + + buf = malloc0(offsetof(struct boot_option, title) + title_len + sizeof(struct drive_path) + sizeof(struct device_path) + path_len); if (!buf) @@ -561,12 +579,12 @@ int efi_add_boot_option( devicep->type = MEDIA_DEVICE_PATH; devicep->sub_type = MEDIA_HARDDRIVE_DP; devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path); - devicep->drive.part_nr = part; - devicep->drive.part_start = pstart; - devicep->drive.part_size = psize; - devicep->drive.signature_type = SIGNATURE_TYPE_GUID; - devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; + memcpy(&devicep->drive.part_nr, &part, sizeof(uint32_t)); + memcpy(&devicep->drive.part_start, &pstart, sizeof(uint64_t)); + memcpy(&devicep->drive.part_size, &psize, sizeof(uint64_t)); id128_to_efi_guid(part_uuid, devicep->drive.signature); + devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; + devicep->drive.signature_type = SIGNATURE_TYPE_GUID; size += devicep->length; /* path to loader */ @@ -630,7 +648,7 @@ int efi_set_boot_order(uint16_t *order, size_t n) { return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t)); } -static int boot_id_hex(const char s[4]) { +static int boot_id_hex(const char s[static 4]) { int id = 0, i; for (i = 0; i < 4; i++) diff --git a/src/shared/install.c b/src/shared/install.c index 3104043af6..8629304cef 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -68,7 +68,7 @@ typedef struct { size_t n_rules; } Presets; -static inline bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) { +static bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) { assert(i); return !strv_isempty(i->aliases) || @@ -76,13 +76,13 @@ static inline bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i !strv_isempty(i->required_by); } -static inline bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) { +static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) { assert(i); return !strv_isempty(i->also); } -static inline void presets_freep(Presets *p) { +static void presets_freep(Presets *p) { size_t i; if (!p) diff --git a/src/shared/journal-importer.c b/src/shared/journal-importer.c index b0e619205d..8638cd3cc9 100644 --- a/src/shared/journal-importer.c +++ b/src/shared/journal-importer.c @@ -23,6 +23,9 @@ enum { }; static int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) { + if (iovw->count >= ENTRY_FIELD_COUNT_MAX) + return -E2BIG; + if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1)) return log_oom(); @@ -97,7 +100,7 @@ static int get_line(JournalImporter *imp, char **line, size_t *size) { imp->scanned = imp->filled; if (imp->scanned >= DATA_SIZE_MAX) - return log_error_errno(SYNTHETIC_ERRNO(E2BIG), + return log_error_errno(SYNTHETIC_ERRNO(ENOBUFS), "Entry is bigger than %u bytes.", DATA_SIZE_MAX); diff --git a/src/shared/journal-importer.h b/src/shared/journal-importer.h index 53354b7c78..7914c0cf5f 100644 --- a/src/shared/journal-importer.h +++ b/src/shared/journal-importer.h @@ -21,6 +21,9 @@ #endif #define LINE_CHUNK 8*1024u +/* The maximum number of fields in an entry */ +#define ENTRY_FIELD_COUNT_MAX 1024 + struct iovec_wrapper { struct iovec *iovec; size_t size_bytes; diff --git a/src/shared/json.c b/src/shared/json.c index 59c4617592..3786ff12b8 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -979,6 +979,8 @@ bool json_variant_has_type(JsonVariant *v, JsonVariantType type) { JsonVariantType rt; v = json_variant_dereference(v); + if (!v) + return false; rt = json_variant_type(v); if (rt == type) @@ -3140,10 +3142,7 @@ int json_log_internal( va_list ap; int r; - if (error < 0) - error = -error; - - errno = error; + errno = ERRNO_VALUE(error); va_start(ap, format); (void) vsnprintf(buffer, sizeof buffer, format, ap); diff --git a/src/shared/json.h b/src/shared/json.h index 4eba91c272..f8e035cda1 100644 --- a/src/shared/json.h +++ b/src/shared/json.h @@ -1,5 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ - #pragma once #include <stdbool.h> @@ -154,7 +153,7 @@ typedef enum JsonFormatFlags { JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */ JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */ JSON_FORMAT_COLOR = 1 << 2, /* insert ANSI color sequences */ - JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insetr ANSI color sequences if colors_enabled() says so */ + JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insert ANSI color sequences if colors_enabled() says so */ JSON_FORMAT_SOURCE = 1 << 4, /* prefix with source filename/line/column */ JSON_FORMAT_SSE = 1 << 5, /* prefix/suffix with W3C server-sent events */ JSON_FORMAT_SEQ = 1 << 6, /* prefix/suffix with RFC 7464 application/json-seq */ diff --git a/src/shared/lockfile-util.c b/src/shared/lockfile-util.c index 4bae23b243..260c2088d5 100644 --- a/src/shared/lockfile-util.c +++ b/src/shared/lockfile-util.c @@ -12,6 +12,7 @@ #include "fs-util.h" #include "lockfile-util.h" #include "macro.h" +#include "missing_fcntl.h" #include "path-util.h" int make_lock_file(const char *p, int operation, LockFile *ret) { diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 525a948f36..15ef0f19ff 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -724,7 +724,7 @@ void json_escape( fputs(" ]", f); } else { - fputc('\"', f); + fputc('"', f); while (l > 0) { if (IN_SET(*p, '"', '\\')) { @@ -741,7 +741,7 @@ void json_escape( l--; } - fputc('\"', f); + fputc('"', f); } } diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 872c25c3dc..bf426eb8bc 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -45,11 +45,11 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) { *d = (LoopDevice) { .fd = copy, .nr = -1, + .relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */ }; *ret = d; - - return 0; + return d->fd; } r = stat_verify_regular(&st); @@ -88,8 +88,7 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) { }; *ret = d; - - return (*ret)->fd; + return d->fd; } int loop_device_make_by_path(const char *path, int open_flags, LoopDevice **ret) { diff --git a/src/shared/pager.c b/src/shared/pager.c index ce4ca9bdb2..bf2597e65a 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -173,7 +173,7 @@ int pager_open(PagerFlags flags) { execvp(pager_args[0], pager_args); log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, - "Failed execute %s, using fallback pagers: %m", pager_args[0]); + "Failed to execute '%s', using fallback pagers: %m", pager_args[0]); } /* Debian's alternatives command for pagers is @@ -190,7 +190,7 @@ int pager_open(PagerFlags flags) { } execlp(exe, exe, NULL); log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, - "Failed execute %s, using next fallback pager: %m", exe); + "Failed to execute '%s', using next fallback pager: %m", exe); } r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in") + 1, false); diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 42d6dd2a94..cc58b3c078 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -793,7 +793,6 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "ioprio_get\0" "kcmp\0" "madvise\0" - "mincore\0" "mprotect\0" "mremap\0" "name_to_handle_at\0" diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index ee31c448fc..dbb4622312 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -83,7 +83,7 @@ int switch_root(const char *new_root, (void) mkdir_p_label(chased, 0755); if (mount(i, chased, NULL, mount_flags, NULL) < 0) - return log_error_errno(r, "Failed to mount %s to %s: %m", i, chased); + return log_error_errno(errno, "Failed to mount %s to %s: %m", i, chased); } /* Do not fail if base_filesystem_create() fails. Not all switch roots are like base_filesystem_create() wants diff --git a/src/shared/xml.c b/src/shared/xml.c index cb34d870c1..2709076264 100644 --- a/src/shared/xml.c +++ b/src/shared/xml.c @@ -191,7 +191,7 @@ int xml_tokenize(const char **p, char **name, void **state, unsigned *line) { if (*c == '=') { c++; - if (IN_SET(*c, '\'', '\"')) { + if (IN_SET(*c, '\'', '"')) { /* Tag with a quoted value */ e = strchr(c+1, *c); |
