mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 14:17:41 +00:00
postfix-3.8-20230406
This commit is contained in:
committed by
Viktor Dukhovni
parent
7b4ef3b6e1
commit
8c9a1f419c
@@ -26990,11 +26990,13 @@ Apologies for any names omitted.
|
||||
20230330
|
||||
|
||||
Safety: the long form { name = value } in import_environment
|
||||
or export_environment is not documented, but accepted, and
|
||||
it was stored in the process environment as the invalid
|
||||
form "name = value" instead of the expected "name=value".
|
||||
Found during code maintenance. Also refined an "empty name"
|
||||
check. Files: clean_env.c, split_nameval.c.
|
||||
or export_environment is not documented, but it is accepted,
|
||||
and it was stored in the process environment as the invalid
|
||||
form "name = value, thus not setting or overriding an entry
|
||||
for "name". This form is now stored as the expected
|
||||
"name=value". Found during code maintenance. Also refined
|
||||
the "missing attribute name" detection. Files: clean_env.c,
|
||||
split_nameval.c.
|
||||
|
||||
20230402
|
||||
|
||||
@@ -27014,3 +27016,23 @@ Apologies for any names omitted.
|
||||
example, inline maps. Added Valgrind support to the namadr_list
|
||||
unit test. Files: util/match_list.c, global/namadr_list.in,
|
||||
util/Makefile.in.
|
||||
|
||||
20240406
|
||||
|
||||
Bugfix (introduced: 20230402): after a change in the DNS_RR
|
||||
structure, the dns_rr_copy() function had not been updated,
|
||||
causing the Postfix SMTP client to panic as it detected a
|
||||
double-free() attempt. Reported by Florian Piekert. File:
|
||||
dns/dns_rr.c.
|
||||
|
||||
Usability: Postfix does not support #comments after other
|
||||
text, but people add them anyway, with unexpected results.
|
||||
The postconf command now warns for trailing comments in
|
||||
main.cf files. Similar warnings are planned for database
|
||||
client configuration files. Files: util/mystrtok.c,
|
||||
util/mystrtok.ref, util/match_list.c, global/namadr_list.ref,
|
||||
postconf/postconf_dbms.c, postconf/test71.ref.
|
||||
|
||||
TODO: #comment after text in DB client configuration files.
|
||||
|
||||
TOIDO: test for dns_rr_copy() + dns_rr_free().
|
||||
|
@@ -1800,3 +1800,4 @@ Stringify
|
||||
bitcount
|
||||
bytecount
|
||||
ipproto
|
||||
cw
|
||||
|
@@ -160,6 +160,9 @@ DNS_RR *dns_rr_create(const char *qname, const char *rname,
|
||||
{
|
||||
DNS_RR *rr;
|
||||
|
||||
/*
|
||||
* Note: if this function is changed, update dns_rr_copy().
|
||||
*/
|
||||
rr = (DNS_RR *) mymalloc(sizeof(*rr));
|
||||
rr->qname = mystrdup(qname);
|
||||
rr->rname = mystrdup(rname);
|
||||
@@ -200,16 +203,17 @@ void dns_rr_free(DNS_RR *rr)
|
||||
|
||||
DNS_RR *dns_rr_copy(DNS_RR *src)
|
||||
{
|
||||
ssize_t len = sizeof(*src) + src->data_len - 1;
|
||||
DNS_RR *dst;
|
||||
|
||||
/*
|
||||
* Combine struct assignment and data copy in one block copy operation.
|
||||
* Note: struct copy, because dns_rr_create() would not copy all fields.
|
||||
*/
|
||||
dst = (DNS_RR *) mymalloc(len);
|
||||
memcpy((void *) dst, (void *) src, len);
|
||||
dst = (DNS_RR *) mymalloc(sizeof(*dst));
|
||||
memcpy((void *) dst, (void *) src, sizeof(*dst));
|
||||
dst->qname = mystrdup(src->qname);
|
||||
dst->rname = mystrdup(src->rname);
|
||||
if (dst->data)
|
||||
dst->data = mymemdup(dst->data, dst->data_len);
|
||||
dst->next = 0;
|
||||
return (dst);
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20230402"
|
||||
#define MAIL_RELEASE_DATE "20230406"
|
||||
#define MAIL_VERSION_NUMBER "3.8"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@@ -51,9 +51,9 @@ bar/168.100.3.3: ERROR
|
||||
./namadr_list: warning: non-existent:/tmp/nosuchfile is unavailable. open file /tmp/nosuchfile: No such file or directory
|
||||
./namadr_list: warning: command line: non-existent:/tmp/nosuchfile: table lookup problem
|
||||
bar/168.100.3.3: ERROR
|
||||
./namadr_list: warning: command line: comment at end of line is not supported: #text
|
||||
./namadr_list: warning: command line: #comment after other text is not allowed: #text ...
|
||||
foo/1.2.3.4: YES
|
||||
./namadr_list: warning: command line: comment at end of line is not supported: #text
|
||||
./namadr_list: warning: command line: #comment after other text is not allowed: #text ...
|
||||
fool/1.2.3.4: NO
|
||||
foo/1.2.3.4: YES
|
||||
bar/1.2.3.4: YES
|
||||
|
@@ -55,7 +55,7 @@ tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \
|
||||
test31 test32 test33 test34 test35 test36 test37 test39 test40 test41 \
|
||||
test42 test43 test44 test45 test46 test47 test48 test49 test50 test51 \
|
||||
test52 test53 test54 test55 test56 test57 test58 test59 test60 test61 \
|
||||
test62 test63 test64 test65 test66 test67 test68 test69 test70
|
||||
test62 test63 test64 test65 test66 test67 test68 test69 test70 test71
|
||||
|
||||
root_tests:
|
||||
|
||||
@@ -964,7 +964,24 @@ test70: $(PROG) test70.ref
|
||||
touch -t 197101010000 main.cf
|
||||
$(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test70.tmp 2>&1
|
||||
diff test70.ref test70.tmp
|
||||
rm -f main.cf master.cf test70.tmp test70.cf
|
||||
rm -f main.cf master.cf test70.tmp
|
||||
|
||||
test71: $(PROG) test71.ref
|
||||
rm -f main.cf master.cf
|
||||
touch main.cf master.cf
|
||||
echo "smtpd_client_restrictions = inline:{" >>main.cf
|
||||
echo " { aaa0 = #aaa1 } #aaa2" >>main.cf
|
||||
echo " }" >>main.cf
|
||||
echo "smtpd_helo_restrictions = pcre:{" >>main.cf
|
||||
echo " { /bbb0 #bbb1/ } #bbb2" >>main.cf
|
||||
echo " }" >>main.cf
|
||||
echo "smtpd_sender_restrictions = regexp:{" >>main.cf
|
||||
echo " { /ccc0 #ccc1/ } #ccc2" >>main.cf
|
||||
echo " }" >>main.cf
|
||||
touch -t 197101010000 main.cf
|
||||
$(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test71.tmp 2>&1
|
||||
diff test71.ref test71.tmp
|
||||
rm -f main.cf master.cf test71.tmp
|
||||
|
||||
printfck: $(OBJS) $(PROG)
|
||||
rm -rf printfck
|
||||
@@ -1072,8 +1089,10 @@ postconf_dbms.o: ../../include/dict_ht.h
|
||||
postconf_dbms.o: ../../include/dict_ldap.h
|
||||
postconf_dbms.o: ../../include/dict_memcache.h
|
||||
postconf_dbms.o: ../../include/dict_mysql.h
|
||||
postconf_dbms.o: ../../include/dict_pcre.h
|
||||
postconf_dbms.o: ../../include/dict_pgsql.h
|
||||
postconf_dbms.o: ../../include/dict_proxy.h
|
||||
postconf_dbms.o: ../../include/dict_regexp.h
|
||||
postconf_dbms.o: ../../include/dict_sqlite.h
|
||||
postconf_dbms.o: ../../include/htable.h
|
||||
postconf_dbms.o: ../../include/mac_expand.h
|
||||
|
@@ -48,6 +48,8 @@
|
||||
/* Google, Inc.
|
||||
/* 111 8th Avenue
|
||||
/* New York, NY 10011, USA
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
@@ -77,6 +79,8 @@
|
||||
#include <dict_pgsql.h>
|
||||
#include <dict_sqlite.h>
|
||||
#include <dict_memcache.h>
|
||||
#include <dict_regexp.h>
|
||||
#include <dict_pcre.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -134,18 +138,31 @@ static const char *pcf_memcache_suffixes[] = {
|
||||
*/
|
||||
typedef struct {
|
||||
const char *db_type;
|
||||
int db_class;
|
||||
const char **db_suffixes;
|
||||
} PCF_DBMS_INFO;
|
||||
|
||||
#define PCF_DBMS_CLASS_CLIENT (1) /* DB name is client config path */
|
||||
#define PCF_DBMS_CLASS_REGEX (2) /* DB name contains regex patterns */
|
||||
|
||||
static const PCF_DBMS_INFO pcf_dbms_info[] = {
|
||||
DICT_TYPE_LDAP, pcf_ldap_suffixes,
|
||||
DICT_TYPE_MYSQL, pcf_mysql_suffixes,
|
||||
DICT_TYPE_PGSQL, pcf_pgsql_suffixes,
|
||||
DICT_TYPE_SQLITE, pcf_sqlite_suffixes,
|
||||
DICT_TYPE_MEMCACHE, pcf_memcache_suffixes,
|
||||
0,
|
||||
{DICT_TYPE_LDAP, PCF_DBMS_CLASS_CLIENT, pcf_ldap_suffixes},
|
||||
{DICT_TYPE_MYSQL, PCF_DBMS_CLASS_CLIENT, pcf_mysql_suffixes},
|
||||
{DICT_TYPE_PGSQL, PCF_DBMS_CLASS_CLIENT, pcf_pgsql_suffixes},
|
||||
{DICT_TYPE_SQLITE, PCF_DBMS_CLASS_CLIENT, pcf_sqlite_suffixes},
|
||||
{DICT_TYPE_MEMCACHE, PCF_DBMS_CLASS_CLIENT, pcf_memcache_suffixes},
|
||||
{DICT_TYPE_REGEXP, PCF_DBMS_CLASS_REGEX},
|
||||
{DICT_TYPE_PCRE, PCF_DBMS_CLASS_REGEX},
|
||||
{0},
|
||||
};
|
||||
|
||||
/*
|
||||
* Workaround to prevent a false warning about "#comment after other text",
|
||||
* when an inline pcre or regexp pattern contains "#text".
|
||||
*/
|
||||
#define PCF_DBMS_RECURSE 1 /* Parse inline {map-entry} */
|
||||
#define PCF_DBMS_NO_RECURSE 0 /* Don't parse inline {map-entry} */
|
||||
|
||||
/* pcf_check_dbms_client - look for unused names in client configuration */
|
||||
|
||||
static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file)
|
||||
@@ -216,7 +233,8 @@ static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file)
|
||||
|
||||
static void pcf_register_dbms_helper(char *str_value,
|
||||
const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *),
|
||||
PCF_MASTER_ENT *local_scope)
|
||||
PCF_MASTER_ENT *local_scope,
|
||||
int recurse)
|
||||
{
|
||||
const PCF_DBMS_INFO *dp;
|
||||
char *db_type;
|
||||
@@ -229,7 +247,8 @@ static void pcf_register_dbms_helper(char *str_value,
|
||||
* Naive parsing. We don't really know if this substring specifies a
|
||||
* database or some other text.
|
||||
*/
|
||||
while ((db_type = mystrtokq(&str_value, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
|
||||
while ((db_type = mystrtokq_cw(&str_value, CHARS_COMMA_SP, CHARS_BRACE,
|
||||
local_scope ? MASTER_CONF_FILE : MAIN_CONF_FILE)) != 0) {
|
||||
if (*db_type == CHARS_BRACE[0]) {
|
||||
if ((err = extpar(&db_type, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) {
|
||||
/* XXX Encapsulate this in pcf_warn() function. */
|
||||
@@ -240,7 +259,9 @@ static void pcf_register_dbms_helper(char *str_value,
|
||||
msg_warn("%s: %s", MAIN_CONF_FILE, err);
|
||||
myfree(err);
|
||||
}
|
||||
pcf_register_dbms_helper(db_type, flag_parameter, local_scope);
|
||||
if (recurse)
|
||||
pcf_register_dbms_helper(db_type, flag_parameter, local_scope,
|
||||
recurse);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -267,7 +288,8 @@ static void pcf_register_dbms_helper(char *str_value,
|
||||
if (*prefix == '/') {
|
||||
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
|
||||
if (strcmp(db_type, dp->db_type) == 0) {
|
||||
pcf_check_dbms_client(dp, prefix);
|
||||
if (dp->db_class == PCF_DBMS_CLASS_CLIENT)
|
||||
pcf_check_dbms_client(dp, prefix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -282,6 +304,8 @@ static void pcf_register_dbms_helper(char *str_value,
|
||||
* local or global namespace.
|
||||
*/
|
||||
if (*prefix != '.') {
|
||||
int next_recurse = recurse;
|
||||
|
||||
if (*prefix == CHARS_BRACE[0]) {
|
||||
if ((err = extpar(&prefix, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) {
|
||||
/* XXX Encapsulate this in pcf_warn() function. */
|
||||
@@ -293,18 +317,28 @@ static void pcf_register_dbms_helper(char *str_value,
|
||||
msg_warn("%s: %s", MAIN_CONF_FILE, err);
|
||||
myfree(err);
|
||||
}
|
||||
pcf_register_dbms_helper(prefix, flag_parameter, local_scope);
|
||||
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
|
||||
if (strcmp(db_type, dp->db_type) == 0) {
|
||||
if (dp->db_class == PCF_DBMS_CLASS_REGEX)
|
||||
next_recurse = PCF_DBMS_NO_RECURSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pcf_register_dbms_helper(prefix, flag_parameter, local_scope,
|
||||
next_recurse);
|
||||
continue;
|
||||
} else {
|
||||
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
|
||||
if (strcmp(db_type, dp->db_type) == 0) {
|
||||
for (cpp = dp->db_suffixes; *cpp; cpp++) {
|
||||
vstring_sprintf(candidate ? candidate :
|
||||
if (dp->db_class == PCF_DBMS_CLASS_CLIENT) {
|
||||
for (cpp = dp->db_suffixes; *cpp; cpp++) {
|
||||
vstring_sprintf(candidate ? candidate :
|
||||
(candidate = vstring_alloc(30)),
|
||||
"%s_%s", prefix, *cpp);
|
||||
flag_parameter(STR(candidate),
|
||||
"%s_%s", prefix, *cpp);
|
||||
flag_parameter(STR(candidate),
|
||||
PCF_PARAM_FLAG_DBMS | PCF_PARAM_FLAG_USER,
|
||||
local_scope);
|
||||
local_scope);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -332,7 +366,7 @@ void pcf_register_dbms_parameters(const char *param_value,
|
||||
buffer = vstring_alloc(100);
|
||||
bufp = pcf_expand_parameter_value(buffer, PCF_SHOW_EVAL, param_value,
|
||||
local_scope);
|
||||
pcf_register_dbms_helper(bufp, flag_parameter, local_scope);
|
||||
pcf_register_dbms_helper(bufp, flag_parameter, local_scope, PCF_DBMS_RECURSE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
8
postfix/src/postconf/test71.ref
Normal file
8
postfix/src/postconf/test71.ref
Normal file
@@ -0,0 +1,8 @@
|
||||
./postconf: warning: main.cf: #comment after other text is not allowed: #aaa1 ...
|
||||
./postconf: warning: main.cf: #comment after other text is not allowed: #aaa2 ...
|
||||
./postconf: warning: main.cf: #comment after other text is not allowed: #ccc2 ...
|
||||
./postconf: warning: main.cf: #comment after other text is not allowed: #bbb2 ...
|
||||
config_directory = .
|
||||
smtpd_client_restrictions = inline:{ { aaa0 = #aaa1 } #aaa2 }
|
||||
smtpd_helo_restrictions = pcre:{ { /bbb0 #bbb1/ } #bbb2 }
|
||||
smtpd_sender_restrictions = regexp:{ { /ccc0 #ccc1/ } #ccc2 }
|
@@ -2419,6 +2419,7 @@ myrand.o: myrand.c
|
||||
myrand.o: myrand.h
|
||||
myrand.o: sys_defs.h
|
||||
mystrtok.o: check_arg.h
|
||||
mystrtok.o: msg.h
|
||||
mystrtok.o: mystrtok.c
|
||||
mystrtok.o: stringops.h
|
||||
mystrtok.o: sys_defs.h
|
||||
|
@@ -84,6 +84,8 @@
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
@@ -145,12 +147,8 @@ static ARGV *match_list_parse(MATCH_LIST *match_list, ARGV *pat_list,
|
||||
* If there is an error, implement graceful degradation by inserting a
|
||||
* pseudo table whose lookups fail with a warning message.
|
||||
*/
|
||||
while ((start = mystrtokq(&bp, delim, CHARS_BRACE)) != 0) {
|
||||
if (*start == '#') {
|
||||
msg_warn("%s: comment at end of line is not supported: %s %s",
|
||||
match_list->pname, start, bp);
|
||||
break;
|
||||
}
|
||||
while ((start = mystrtokq_cw(&bp, delim, CHARS_BRACE,
|
||||
match_list->pname)) != 0) {
|
||||
for (match = init_match, item = start; *item == '!'; item++)
|
||||
match = !match;
|
||||
if (*item == 0)
|
||||
|
@@ -18,6 +18,22 @@
|
||||
/* char *mystrtokdq(bufp, delimiters)
|
||||
/* char **bufp;
|
||||
/* const char *delimiters;
|
||||
/*
|
||||
/* char *mystrtok_cw(bufp, delimiters, blame)
|
||||
/* char **bufp;
|
||||
/* const char *delimiters;
|
||||
/* const char *blame;
|
||||
/*
|
||||
/* char *mystrtokq_cw(bufp, delimiters, parens, blame)
|
||||
/* char **bufp;
|
||||
/* const char *delimiters;
|
||||
/* const char *parens;
|
||||
/* const char *blame;
|
||||
/*
|
||||
/* char *mystrtokdq_cw(bufp, delimiters, blame)
|
||||
/* char **bufp;
|
||||
/* const char *delimiters;
|
||||
/* const char *blame;
|
||||
/* DESCRIPTION
|
||||
/* mystrtok() splits a buffer on the specified \fIdelimiters\fR.
|
||||
/* Tokens are delimited by runs of delimiters, so this routine
|
||||
@@ -38,6 +54,12 @@
|
||||
/*
|
||||
/* The result value is the next token, or a null pointer when the
|
||||
/* end of the buffer was reached.
|
||||
/*
|
||||
/* mystrtok_cw(), mystrtokq_cw(), and mystrtokdq_cw, log a
|
||||
/* warning and return null when the result would look like
|
||||
/* comment. The \fBblame\fR argument provides context for
|
||||
/* warning messages. Specify a null pointer to disable the
|
||||
/* comment check.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -52,20 +74,40 @@
|
||||
/* Google, Inc.
|
||||
/* 111 8th Avenue
|
||||
/* New York, NY 10011, USA
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
#include <sys_defs.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "stringops.h"
|
||||
#include <msg.h>
|
||||
#include <stringops.h>
|
||||
|
||||
/* mystrtok_warn - warn for #comment after other text */
|
||||
|
||||
static void mystrtok_warn(const char *start, const char *bufp, const char *blame)
|
||||
{
|
||||
msg_warn("%s: #comment after other text is not allowed: %s %.20s...",
|
||||
blame, start, bufp);
|
||||
}
|
||||
|
||||
/* mystrtok - ABI compatibility wrapper */
|
||||
|
||||
#undef mystrtok
|
||||
|
||||
char *mystrtok(char **src, const char *sep)
|
||||
{
|
||||
return (mystrtok_cw(src, sep, (char *) 0));
|
||||
}
|
||||
|
||||
/* mystrtok - safe tokenizer */
|
||||
|
||||
char *mystrtok(char **src, const char *sep)
|
||||
char *mystrtok_cw(char **src, const char *sep, const char *blame)
|
||||
{
|
||||
char *start = *src;
|
||||
char *end;
|
||||
@@ -86,12 +128,28 @@ char *mystrtok(char **src, const char *sep)
|
||||
if (*end != 0)
|
||||
*end++ = 0;
|
||||
*src = end;
|
||||
return (start);
|
||||
|
||||
if (blame && *start == '#') {
|
||||
mystrtok_warn(start, *src, blame);
|
||||
return (0);
|
||||
} else {
|
||||
return (start);
|
||||
}
|
||||
}
|
||||
|
||||
/* mystrtokq - safe tokenizer with quoting support */
|
||||
/* mystrtokq - ABI compatibility wrapper */
|
||||
|
||||
#undef mystrtokq
|
||||
|
||||
char *mystrtokq(char **src, const char *sep, const char *parens)
|
||||
{
|
||||
return (mystrtokq_cw(src, sep, parens, (char *) 0));
|
||||
}
|
||||
|
||||
/* mystrtokq_cw - safe tokenizer with quoting support */
|
||||
|
||||
char *mystrtokq_cw(char **src, const char *sep, const char *parens,
|
||||
const char *blame)
|
||||
{
|
||||
char *start = *src;
|
||||
static char *cp;
|
||||
@@ -121,12 +179,27 @@ char *mystrtokq(char **src, const char *sep, const char *parens)
|
||||
}
|
||||
}
|
||||
*src = cp;
|
||||
return (start);
|
||||
|
||||
if (blame && *start == '#') {
|
||||
mystrtok_warn(start, *src, blame);
|
||||
return (0);
|
||||
} else {
|
||||
return (start);
|
||||
}
|
||||
}
|
||||
|
||||
/* mystrtokdq - safe tokenizer, double quote and backslash support */
|
||||
/* mystrtokdq - ABI compatibility wrapper */
|
||||
|
||||
#undef mystrtokdq
|
||||
|
||||
char *mystrtokdq(char **src, const char *sep)
|
||||
{
|
||||
return (mystrtokdq_cw(src, sep, (char *) 0));
|
||||
}
|
||||
|
||||
/* mystrtokdq_cw - safe tokenizer, double quote and backslash support */
|
||||
|
||||
char *mystrtokdq_cw(char **src, const char *sep, const char *blame)
|
||||
{
|
||||
char *cp = *src;
|
||||
char *start;
|
||||
@@ -157,7 +230,13 @@ char *mystrtokdq(char **src, const char *sep)
|
||||
}
|
||||
}
|
||||
*src = cp;
|
||||
return (start);
|
||||
|
||||
if (blame && start && *start == '#') {
|
||||
mystrtok_warn(start, *src, blame);
|
||||
return (0);
|
||||
} else {
|
||||
return (start);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
@@ -195,6 +274,12 @@ static const struct testcase testcases[] = {
|
||||
{"mystrtokdq", " foo\\ bar ", {"foo\\ bar"}},
|
||||
{"mystrtokdq", " foo \\\" bar", {"foo", "\\\"", "bar"}},
|
||||
{"mystrtokdq", " foo \" bar baz\" ", {"foo", "\" bar baz\""}},
|
||||
{"mystrtok_cw", "#after text"},
|
||||
{"mystrtok_cw", "before-text #after text", {"before-text"}},
|
||||
{"mystrtokq_cw", "#after text"},
|
||||
{"mystrtokq_cw", "{ before text } #after text", "{ before text }"},
|
||||
{"mystrtokdq_cw", "#after text"},
|
||||
{"mystrtokdq_cw", "\"before text\" #after text", {"\"before text\""}},
|
||||
};
|
||||
|
||||
int main(void)
|
||||
@@ -229,6 +314,12 @@ int main(void)
|
||||
actual = mystrtokq(&cp, CHARS_SPACE, CHARS_BRACE);
|
||||
} else if (strcmp(tp->action, "mystrtokdq") == 0) {
|
||||
actual = mystrtokdq(&cp, CHARS_SPACE);
|
||||
} else if (strcmp(tp->action, "mystrtok_cw") == 0) {
|
||||
actual = mystrtok_cw(&cp, CHARS_SPACE, "test");
|
||||
} else if (strcmp(tp->action, "mystrtokq_cw") == 0) {
|
||||
actual = mystrtokq_cw(&cp, CHARS_SPACE, CHARS_BRACE, "test");
|
||||
} else if (strcmp(tp->action, "mystrtokdq_cw") == 0) {
|
||||
actual = mystrtokdq_cw(&cp, CHARS_SPACE, "test");
|
||||
} else {
|
||||
msg_panic("invalid command: %s", tp->action);
|
||||
}
|
||||
|
@@ -28,3 +28,21 @@ unknown: RUN test case 13 mystrtokdq > foo \" bar<
|
||||
unknown: PASS test 13
|
||||
unknown: RUN test case 14 mystrtokdq > foo " bar baz" <
|
||||
unknown: PASS test 14
|
||||
unknown: RUN test case 15 mystrtok_cw >#after text<
|
||||
unknown: warning: test: #comment after other text is not allowed: #after text...
|
||||
unknown: PASS test 15
|
||||
unknown: RUN test case 16 mystrtok_cw >before-text #after text<
|
||||
unknown: warning: test: #comment after other text is not allowed: #after text...
|
||||
unknown: PASS test 16
|
||||
unknown: RUN test case 17 mystrtokq_cw >#after text<
|
||||
unknown: warning: test: #comment after other text is not allowed: #after text...
|
||||
unknown: PASS test 17
|
||||
unknown: RUN test case 18 mystrtokq_cw >{ before text } #after text<
|
||||
unknown: warning: test: #comment after other text is not allowed: #after text...
|
||||
unknown: PASS test 18
|
||||
unknown: RUN test case 19 mystrtokdq_cw >#after text<
|
||||
unknown: warning: test: #comment after other text is not allowed: #after text...
|
||||
unknown: PASS test 19
|
||||
unknown: RUN test case 20 mystrtokdq_cw >"before text" #after text<
|
||||
unknown: warning: test: #comment after other text is not allowed: #after text...
|
||||
unknown: PASS test 20
|
||||
|
@@ -31,8 +31,15 @@ extern char *concatenate(const char *,...);
|
||||
extern char *mystrtok(char **, const char *);
|
||||
extern char *mystrtokq(char **, const char *, const char *);
|
||||
extern char *mystrtokdq(char **, const char *);
|
||||
extern char *mystrtok_cw(char **, const char *, const char *);
|
||||
extern char *mystrtokq_cw(char **, const char *, const char *, const char *);
|
||||
extern char *mystrtokdq_cw(char **, const char *, const char *);
|
||||
extern char *translit(char *, const char *, const char *);
|
||||
|
||||
#define mystrtok(cp, sp) mystrtok_cw((cp), (sp), (char *) 0)
|
||||
#define mystrtokq(cp, sp, pp) mystrtokq_cw((cp), (sp), (pp), (char *) 0)
|
||||
#define mystrtokdq(cp, sp) mystrtokdq_cw((cp), (sp), (char *) 0)
|
||||
|
||||
#define printable(string, replacement) \
|
||||
printable_except((string), (replacement), (char *) 0)
|
||||
|
||||
@@ -102,6 +109,8 @@ extern int strncasecmp_utf8x(int, const char *, const char *, ssize_t);
|
||||
/* Google, Inc.
|
||||
/* 111 8th Avenue
|
||||
/* New York, NY 10011, USA
|
||||
/*
|
||||
/* Wietse Venema
|
||||
/*--*/
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user