diff options
Diffstat (limited to 'src/src/lookups')
-rw-r--r-- | src/src/lookups/dnsdb.c | 64 | ||||
-rw-r--r-- | src/src/lookups/ibase.c | 560 | ||||
-rw-r--r-- | src/src/lookups/ldap.c | 54 | ||||
-rw-r--r-- | src/src/lookups/lf_functions.h | 2 | ||||
-rw-r--r-- | src/src/lookups/lf_quote.c | 23 | ||||
-rw-r--r-- | src/src/lookups/lsearch.c | 20 | ||||
-rw-r--r-- | src/src/lookups/mysql.c | 35 | ||||
-rw-r--r-- | src/src/lookups/nisplus.c | 39 | ||||
-rw-r--r-- | src/src/lookups/oracle.c | 63 | ||||
-rw-r--r-- | src/src/lookups/pgsql.c | 70 | ||||
-rw-r--r-- | src/src/lookups/redis.c | 45 | ||||
-rw-r--r-- | src/src/lookups/sqlite.c | 31 |
12 files changed, 473 insertions, 533 deletions
diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c index bf3acd6ef..9e95b9038 100644 --- a/src/src/lookups/dnsdb.c +++ b/src/src/lookups/dnsdb.c @@ -14,17 +14,17 @@ header files. */ #ifndef T_TXT -#define T_TXT 16 +# define T_TXT 16 #endif /* Many systems do not have T_SPF. */ #ifndef T_SPF -#define T_SPF 99 +# define T_SPF 99 #endif /* New TLSA record for DANE */ #ifndef T_TLSA -#define T_TLSA 52 +# define T_TLSA 52 #endif /* Table of recognized DNS record types and their integer values. */ @@ -134,8 +134,6 @@ dnsdb_find(void *handle, uschar *filename, const uschar *keystring, int length, uschar **result, uschar **errmsg, uint *do_cache) { int rc; -int size = 256; -int ptr = 0; int sep = 0; int defer_mode = PASS; int dnssec_mode = OK; @@ -147,10 +145,10 @@ const uschar *outsep = CUS"\n"; const uschar *outsep2 = NULL; uschar *equals, *domain, *found; -/* Because we're the working in the search pool, we try to reclaim as much +/* Because we're working in the search pool, we try to reclaim as much store as possible later, so we preallocate the result here */ -uschar *yield = store_get(size); +gstring * yield = string_get(256); dns_record *rr; dns_answer dnsa; @@ -380,12 +378,9 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) /* Search the returned records */ - for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) + for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); rr; + rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == searchtype) { - if (rr->type != searchtype) continue; - if (*do_cache > rr->ttl) *do_cache = rr->ttl; @@ -394,8 +389,8 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) dns_address *da; for (da = dns_address_from_rr(&dnsa, rr); da; da = da->next) { - if (ptr != 0) yield = string_catn(yield, &size, &ptr, outsep, 1); - yield = string_cat(yield, &size, &ptr, da->address); + if (yield->ptr) yield = string_catn(yield, outsep, 1); + yield = string_cat(yield, da->address); } continue; } @@ -403,16 +398,12 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) /* Other kinds of record just have one piece of data each, but there may be several of them, of course. */ - if (ptr != 0) yield = string_catn(yield, &size, &ptr, outsep, 1); + if (yield->ptr) yield = string_catn(yield, outsep, 1); if (type == T_TXT || type == T_SPF) { - if (outsep2 == NULL) - { - /* output only the first item of data */ - yield = string_catn(yield, &size, &ptr, US (rr->data+1), - (rr->data)[0]); - } + if (outsep2 == NULL) /* output only the first item of data */ + yield = string_catn(yield, US (rr->data+1), (rr->data)[0]); else { /* output all items */ @@ -421,9 +412,8 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) { uschar chunk_len = (rr->data)[data_offset++]; if (outsep2[0] != '\0' && data_offset != 1) - yield = string_catn(yield, &size, &ptr, outsep2, 1); - yield = string_catn(yield, &size, &ptr, - US ((rr->data)+data_offset), chunk_len); + yield = string_catn(yield, outsep2, 1); + yield = string_catn(yield, US ((rr->data)+data_offset), chunk_len); data_offset += chunk_len; } } @@ -449,7 +439,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) i++) sp += sprintf(CS sp, "%02x", (unsigned char)p[i]); - yield = string_cat(yield, &size, &ptr, s); + yield = string_cat(yield, s); } else /* T_CNAME, T_CSA, T_MX, T_MXH, T_NS, T_PTR, T_SOA, T_SRV */ { @@ -467,7 +457,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) case T_MX: GETSHORT(priority, p); sprintf(CS s, "%d%c", priority, *outsep2); - yield = string_cat(yield, &size, &ptr, s); + yield = string_cat(yield, s); break; case T_SRV: @@ -476,7 +466,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) GETSHORT(port, p); sprintf(CS s, "%d%c%d%c%d%c", priority, *outsep2, weight, *outsep2, port, *outsep2); - yield = string_cat(yield, &size, &ptr, s); + yield = string_cat(yield, s); break; case T_CSA: @@ -505,7 +495,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) } s[1] = ' '; - yield = string_catn(yield, &size, &ptr, s, 2); + yield = string_catn(yield, s, 2); break; default: @@ -526,14 +516,14 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) "domain=%s", dns_text_type(type), domain); break; } - else yield = string_cat(yield, &size, &ptr, s); + else yield = string_cat(yield, s); if (type == T_SOA && outsep2 != NULL) { unsigned long serial, refresh, retry, expire, minimum; p += rc; - yield = string_catn(yield, &size, &ptr, outsep2, 1); + yield = string_catn(yield, outsep2, 1); rc = dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, p, (DN_EXPAND_ARG4_TYPE)s, sizeof(s)); @@ -543,7 +533,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) "domain=%s", dns_text_type(type), domain); break; } - else yield = string_cat(yield, &size, &ptr, s); + else yield = string_cat(yield, s); p += rc; GETLONG(serial, p); GETLONG(refresh, p); @@ -551,7 +541,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) sprintf(CS s, "%c%lu%c%lu%c%lu%c%lu%c%lu", *outsep2, serial, *outsep2, refresh, *outsep2, retry, *outsep2, expire, *outsep2, minimum); - yield = string_cat(yield, &size, &ptr, s); + yield = string_cat(yield, s); } } } /* Loop for list of returned records */ @@ -563,18 +553,18 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) /* Reclaim unused memory */ -store_reset(yield + ptr + 1); +store_reset(yield->s + yield->ptr + 1); -/* If ptr == 0 we have not found anything. Otherwise, insert the terminating +/* If yield NULL we have not found anything. Otherwise, insert the terminating zero and return the result. */ dns_retrans = save_retrans; dns_retry = save_retry; dns_init(FALSE, FALSE, FALSE); /* clear the dnssec bit for getaddrbyname */ -if (ptr == 0) return failrc; -yield[ptr] = 0; -*result = yield; +if (!yield || !yield->ptr) return failrc; + +*result = string_from_gstring(yield); return OK; } diff --git a/src/src/lookups/ibase.c b/src/src/lookups/ibase.c index 7f1775c1f..58bced201 100644 --- a/src/src/lookups/ibase.c +++ b/src/src/lookups/ibase.c @@ -109,332 +109,334 @@ static int perform_ibase_search(uschar * query, uschar * server, uschar ** resultptr, uschar ** errmsg, BOOL * defer_break) { - isc_stmt_handle stmth = NULL; - XSQLDA *out_sqlda; - XSQLVAR *var; - - char buffer[256]; - ISC_STATUS status[20], *statusp = status; - - int i; - int ssize = 0; - int offset = 0; - int yield = DEFER; - uschar *result = NULL; - ibase_connection *cn; - uschar *server_copy = NULL; - uschar *sdata[3]; +isc_stmt_handle stmth = NULL; +XSQLDA *out_sqlda; +XSQLVAR *var; + +char buffer[256]; +ISC_STATUS status[20], *statusp = status; + +gstring * result; +int i; +int yield = DEFER; +ibase_connection *cn; +uschar *server_copy = NULL; +uschar *sdata[3]; /* Disaggregate the parameters from the server argument. The order is host, database, user, password. We can write to the string, since it is in a nextinlist temporary buffer. The copy of the string that is used for caching has the password removed. This copy is also used for debugging output. */ - for (i = 2; i > 0; i--) { - uschar *pp = Ustrrchr(server, '|'); - if (pp == NULL) { - *errmsg = - string_sprintf("incomplete Interbase server data: %s", - (i == 3) ? server : server_copy); - *defer_break = TRUE; - return DEFER; - } - *pp++ = 0; - sdata[i] = pp; - if (i == 2) - server_copy = string_copy(server); /* sans password */ +for (i = 2; i > 0; i--) + { + uschar *pp = Ustrrchr(server, '|'); + + if (pp == NULL) + { + *errmsg = string_sprintf("incomplete Interbase server data: %s", + (i == 3) ? server : server_copy); + *defer_break = TRUE; + return DEFER; } - sdata[0] = server; /* What's left at the start */ + *pp++ = 0; + sdata[i] = pp; + if (i == 2) + server_copy = string_copy(server); /* sans password */ + } +sdata[0] = server; /* What's left at the start */ /* See if we have a cached connection to the server */ - for (cn = ibase_connections; cn != NULL; cn = cn->next) { - if (Ustrcmp(cn->server, server_copy) == 0) { - break; - } - } +for (cn = ibase_connections; cn != NULL; cn = cn->next) + if (Ustrcmp(cn->server, server_copy) == 0) + break; /* Use a previously cached connection ? */ - if (cn != NULL) { - static char db_info_options[] = { isc_info_base_level }; - - /* test if the connection is alive */ - if (isc_database_info - (status, &cn->dbh, sizeof(db_info_options), db_info_options, - sizeof(buffer), buffer)) { - /* error occurred: assume connection is down */ - DEBUG(D_lookup) - debug_printf - ("Interbase cleaning up cached connection: %s\n", - cn->server); - isc_detach_database(status, &cn->dbh); - } else { - DEBUG(D_lookup) - debug_printf("Interbase using cached connection for %s\n", - server_copy); - } - } else { - cn = store_get(sizeof(ibase_connection)); - cn->server = server_copy; - cn->dbh = NULL; - cn->transh = NULL; - cn->next = ibase_connections; - ibase_connections = cn; +if (cn) + { + static char db_info_options[] = { isc_info_base_level }; + + /* test if the connection is alive */ + if (isc_database_info(status, &cn->dbh, sizeof(db_info_options), + db_info_options, sizeof(buffer), buffer)) + { + /* error occurred: assume connection is down */ + DEBUG(D_lookup) + debug_printf + ("Interbase cleaning up cached connection: %s\n", + cn->server); + isc_detach_database(status, &cn->dbh); } + else + { + DEBUG(D_lookup) debug_printf("Interbase using cached connection for %s\n", + server_copy); + } + } +else + { + cn = store_get(sizeof(ibase_connection)); + cn->server = server_copy; + cn->dbh = NULL; + cn->transh = NULL; + cn->next = ibase_connections; + ibase_connections = cn; + } /* If no cached connection, we must set one up. */ - if (cn->dbh == NULL || cn->transh == NULL) { - - char *dpb, *p; - short dpb_length; - static char trans_options[] = - { isc_tpb_version3, isc_tpb_read, isc_tpb_read_committed, - isc_tpb_rec_version - }; - - /* Construct the database parameter buffer. */ - dpb = buffer; - *dpb++ = isc_dpb_version1; - *dpb++ = isc_dpb_user_name; - *dpb++ = strlen(sdata[1]); - for (p = sdata[1]; *p;) - *dpb++ = *p++; - *dpb++ = isc_dpb_password; - *dpb++ = strlen(sdata[2]); - for (p = sdata[2]; *p;) - *dpb++ = *p++; - dpb_length = dpb - buffer; - - DEBUG(D_lookup) - debug_printf("new Interbase connection: database=%s user=%s\n", - sdata[0], sdata[1]); - - /* Connect to the database */ - if (isc_attach_database - (status, 0, sdata[0], &cn->dbh, dpb_length, buffer)) { - isc_interprete(buffer, &statusp); - *errmsg = - string_sprintf("Interbase attach() failed: %s", buffer); - *defer_break = FALSE; - goto IBASE_EXIT; - } - - /* Now start a read-only read-committed transaction */ - if (isc_start_transaction - (status, &cn->transh, 1, &cn->dbh, sizeof(trans_options), - trans_options)) { - isc_interprete(buffer, &statusp); - isc_detach_database(status, &cn->dbh); - *errmsg = - string_sprintf("Interbase start_transaction() failed: %s", - buffer); - *defer_break = FALSE; - goto IBASE_EXIT; - } +if (cn->dbh == NULL || cn->transh == NULL) + { + char *dpb, *p; + short dpb_length; + static char trans_options[] = + { isc_tpb_version3, isc_tpb_read, isc_tpb_read_committed, + isc_tpb_rec_version + }; + + /* Construct the database parameter buffer. */ + dpb = buffer; + *dpb++ = isc_dpb_version1; + *dpb++ = isc_dpb_user_name; + *dpb++ = strlen(sdata[1]); + for (p = sdata[1]; *p;) + *dpb++ = *p++; + *dpb++ = isc_dpb_password; + *dpb++ = strlen(sdata[2]); + for (p = sdata[2]; *p;) + *dpb++ = *p++; + dpb_length = dpb - buffer; + + DEBUG(D_lookup) + debug_printf("new Interbase connection: database=%s user=%s\n", + sdata[0], sdata[1]); + + /* Connect to the database */ + if (isc_attach_database + (status, 0, sdata[0], &cn->dbh, dpb_length, buffer)) + { + isc_interprete(buffer, &statusp); + *errmsg = + string_sprintf("Interbase attach() failed: %s", buffer); + *defer_break = FALSE; + goto IBASE_EXIT; } -/* Run the query */ - if (isc_dsql_allocate_statement(status, &cn->dbh, &stmth)) { - isc_interprete(buffer, &statusp); - *errmsg = - string_sprintf("Interbase alloc_statement() failed: %s", - buffer); - *defer_break = FALSE; - goto IBASE_EXIT; + /* Now start a read-only read-committed transaction */ + if (isc_start_transaction + (status, &cn->transh, 1, &cn->dbh, sizeof(trans_options), + trans_options)) + { + isc_interprete(buffer, &statusp); + isc_detach_database(status, &cn->dbh); + *errmsg = + string_sprintf("Interbase start_transaction() failed: %s", + buffer); + *defer_break = FALSE; + goto IBASE_EXIT; } + } - out_sqlda = store_get(XSQLDA_LENGTH(1)); - out_sqlda->version = SQLDA_VERSION1; - out_sqlda->sqln = 1; - - if (isc_dsql_prepare - (status, &cn->transh, &stmth, 0, query, 1, out_sqlda)) { - isc_interprete(buffer, &statusp); - store_reset(out_sqlda); - out_sqlda = NULL; - *errmsg = - string_sprintf("Interbase prepare_statement() failed: %s", - buffer); - *defer_break = FALSE; - goto IBASE_EXIT; - } +/* Run the query */ +if (isc_dsql_allocate_statement(status, &cn->dbh, &stmth)) + { + isc_interprete(buffer, &statusp); + *errmsg = + string_sprintf("Interbase alloc_statement() failed: %s", + buffer); + *defer_break = FALSE; + goto IBASE_EXIT; + } + +out_sqlda = store_get(XSQLDA_LENGTH(1)); +out_sqlda->version = SQLDA_VERSION1; +out_sqlda->sqln = 1; + +if (isc_dsql_prepare + (status, &cn->transh, &stmth, 0, query, 1, out_sqlda)) + { + isc_interprete(buffer, &statusp); + store_reset(out_sqlda); + out_sqlda = NULL; + *errmsg = + string_sprintf("Interbase prepare_statement() failed: %s", + buffer); + *defer_break = FALSE; + goto IBASE_EXIT; + } /* re-allocate the output structure if there's more than one field */ - if (out_sqlda->sqln < out_sqlda->sqld) { - XSQLDA *new_sqlda = store_get(XSQLDA_LENGTH(out_sqlda->sqld)); - if (isc_dsql_describe - (status, &stmth, out_sqlda->version, new_sqlda)) { - isc_interprete(buffer, &statusp); - isc_dsql_free_statement(status, &stmth, DSQL_drop); - store_reset(out_sqlda); - out_sqlda = NULL; - *errmsg = - string_sprintf("Interbase describe_statement() failed: %s", - buffer); - *defer_break = FALSE; - goto IBASE_EXIT; - } - out_sqlda = new_sqlda; +if (out_sqlda->sqln < out_sqlda->sqld) + { + XSQLDA *new_sqlda = store_get(XSQLDA_LENGTH(out_sqlda->sqld)); + if (isc_dsql_describe + (status, &stmth, out_sqlda->version, new_sqlda)) + { + isc_interprete(buffer, &statusp); + isc_dsql_free_statement(status, &stmth, DSQL_drop); + store_reset(out_sqlda); + out_sqlda = NULL; + *errmsg = string_sprintf("Interbase describe_statement() failed: %s", + buffer); + *defer_break = FALSE; + goto IBASE_EXIT; } + out_sqlda = new_sqlda; + } /* allocate storage for every returned field */ - for (i = 0, var = out_sqlda->sqlvar; i < out_sqlda->sqld; i++, var++) { - switch (var->sqltype & ~1) { - case SQL_VARYING: - var->sqldata = - (char *) store_get(sizeof(char) * var->sqllen + 2); - break; - case SQL_TEXT: - var->sqldata = - (char *) store_get(sizeof(char) * var->sqllen); - break; - case SQL_SHORT: - var->sqldata = CS store_get(sizeof(short)); - break; - case SQL_LONG: - var->sqldata = CS store_get(sizeof(ISC_LONG)); - break; +for (i = 0, var = out_sqlda->sqlvar; i < out_sqlda->sqld; i++, var++) + { + switch (var->sqltype & ~1) + { + case SQL_VARYING: + var->sqldata = CS store_get(sizeof(char) * var->sqllen + 2); + break; + case SQL_TEXT: + var->sqldata = CS store_get(sizeof(char) * var->sqllen); + break; + case SQL_SHORT: + var->sqldata = CS store_get(sizeof(short)); + break; + case SQL_LONG: + var->sqldata = CS store_get(sizeof(ISC_LONG)); + break; #ifdef SQL_INT64 - case SQL_INT64: - var->sqldata = CS store_get(sizeof(ISC_INT64)); - break; + case SQL_INT64: + var->sqldata = CS store_get(sizeof(ISC_INT64)); + break; #endif - case SQL_FLOAT: - var->sqldata = CS store_get(sizeof(float)); - break; - case SQL_DOUBLE: - var->sqldata = CS store_get(sizeof(double)); - break; + case SQL_FLOAT: + var->sqldata = CS store_get(sizeof(float)); + break; + case SQL_DOUBLE: + var->sqldata = CS store_get(sizeof(double)); + break; #ifdef SQL_TIMESTAMP - case SQL_DATE: - var->sqldata = CS store_get(sizeof(ISC_QUAD)); - break; + case SQL_DATE: + var->sqldata = CS store_get(sizeof(ISC_QUAD)); + break; #else - case SQL_TIMESTAMP: - var->sqldata = CS store_get(sizeof(ISC_TIMESTAMP)); - break; - case SQL_TYPE_DATE: - var->sqldata = CS store_get(sizeof(ISC_DATE)); - break; - case SQL_TYPE_TIME: - var->sqldata = CS store_get(sizeof(ISC_TIME)); - break; -#endif - } - if (var->sqltype & 1) { - var->sqlind = (short *) store_get(sizeof(short)); - } + case SQL_TIMESTAMP: + var->sqldata = CS store_get(sizeof(ISC_TIMESTAMP)); + break; + case SQL_TYPE_DATE: + var->sqldata = CS store_get(sizeof(ISC_DATE)); + break; + case SQL_TYPE_TIME: + var->sqldata = CS store_get(sizeof(ISC_TIME)); + break; + #endif } - - /* finally, we're ready to execute the statement */ - if (isc_dsql_execute - (status, &cn->transh, &stmth, out_sqlda->version, NULL)) { - isc_interprete(buffer, &statusp); - *errmsg = - string_sprintf("Interbase describe_statement() failed: %s", - buffer); - isc_dsql_free_statement(status, &stmth, DSQL_drop); - *defer_break = FALSE; - goto IBASE_EXIT; + if (var->sqltype & 1) + var->sqlind = (short *) store_get(sizeof(short)); + } + +/* finally, we're ready to execute the statement */ +if (isc_dsql_execute + (status, &cn->transh, &stmth, out_sqlda->version, NULL)) + { + isc_interprete(buffer, &statusp); + *errmsg = string_sprintf("Interbase describe_statement() failed: %s", + buffer); + isc_dsql_free_statement(status, &stmth, DSQL_drop); + *defer_break = FALSE; + goto IBASE_EXIT; + } + +while (isc_dsql_fetch(status, &stmth, out_sqlda->version, out_sqlda) != 100L) + { + /* check if an error occurred */ + if (status[0] & status[1]) + { + isc_interprete(buffer, &statusp); + *errmsg = + string_sprintf("Interbase fetch() failed: %s", buffer); + isc_dsql_free_statement(status, &stmth, DSQL_drop); + *defer_break = FALSE; + goto IBASE_EXIT; } - while (isc_dsql_fetch(status, &stmth, out_sqlda->version, out_sqlda) != - 100L) { - /* check if an error occurred */ - if (status[0] & status[1]) { - isc_interprete(buffer, &statusp); - *errmsg = - string_sprintf("Interbase fetch() failed: %s", buffer); - isc_dsql_free_statement(status, &stmth, DSQL_drop); - *defer_break = FALSE; - goto IBASE_EXIT; - } - - if (result != NULL) - result = string_catn(result, &ssize, &offset, US "\n", 1); - - /* Find the number of fields returned. If this is one, we don't add field - names to the data. Otherwise we do. */ - if (out_sqlda->sqld == 1) { - if (out_sqlda->sqlvar[0].sqlind == NULL || *out_sqlda->sqlvar[0].sqlind != -1) /* NULL value yields nothing */ - result = - string_catn(result, &ssize, &offset, US buffer, - fetch_field(buffer, sizeof(buffer), - &out_sqlda->sqlvar[0])); - } - - else - for (i = 0; i < out_sqlda->sqld; i++) { - int len = fetch_field(buffer, sizeof(buffer), - &out_sqlda->sqlvar[i]); - - result = - string_cat(result, &ssize, &offset, - US out_sqlda->sqlvar[i].aliasname, - out_sqlda->sqlvar[i].aliasname_length); - result = string_catn(result, &ssize, &offset, US "=", 1); - - /* Quote the value if it contains spaces or is empty */ - - if (*out_sqlda->sqlvar[i].sqlind == -1) { /* NULL value */ - result = - string_catn(result, &ssize, &offset, US "\"\"", 2); - } - - else if (buffer[0] == 0 || Ustrchr(buffer, ' ') != NULL) { - int j; - result = - string_catn(result, &ssize, &offset, US "\"", 1); - for (j = 0; j < len; j++) { - if (buffer[j] == '\"' || buffer[j] == '\\') - result = - string_cat(result, &ssize, &offset, - US "\\", 1); - result = - string_cat(result, &ssize, &offset, - US buffer + j, 1); - } - result = - string_catn(result, &ssize, &offset, US "\"", 1); - } else { - result = - string_catn(result, &ssize, &offset, US buffer, len); - } - result = string_catn(result, &ssize, &offset, US " ", 1); - } + if (result) + result = string_catn(result, US "\n", 1); + + /* Find the number of fields returned. If this is one, we don't add field + names to the data. Otherwise we do. */ + if (out_sqlda->sqld == 1) + { + if (out_sqlda->sqlvar[0].sqlind == NULL || *out_sqlda->sqlvar[0].sqlind != -1) /* NULL value yields nothing */ + result = string_catn(result, US buffer, + fetch_field(buffer, sizeof(buffer), + &out_sqlda->sqlvar[0])); } + else + for (i = 0; i < out_sqlda->sqld; i++) + { + int len = fetch_field(buffer, sizeof(buffer), &out_sqlda->sqlvar[i]); + + result = string_catn(result, US out_sqlda->sqlvar[i].aliasname, + out_sqlda->sqlvar[i].aliasname_length); + result = string_catn(result, US "=", 1); + + /* Quote the value if it contains spaces or is empty */ + + if (*out_sqlda->sqlvar[i].sqlind == -1) /* NULL value */ + result = string_catn(result, US "\"\"", 2); + + else if (buffer[0] == 0 || Ustrchr(buffer, ' ') != NULL) + { + int j; + + result = string_catn(result, US "\"", 1); + for (j = 0; j < len; j++) + { + if (buffer[j] == '\"' || buffer[j] == '\\') + result = string_cat(result, US "\\", 1); + result = string_cat(result, US buffer + j, 1); + } + result = string_catn(result, US "\"", 1); + } + else + result = string_catn(result, US buffer, len); + result = string_catn(result, US " ", 1); + } + } + /* If result is NULL then no data has been found and so we return FAIL. Otherwise, we must terminate the string which has been built; string_cat() always leaves enough room for a terminating zero. */ - if (result == NULL) { - yield = FAIL; - *errmsg = US "Interbase: no data found"; - } else { - result[offset] = 0; - store_reset(result + offset + 1); - } +if (!result) + { + yield = FAIL; + *errmsg = US "Interbase: no data found"; + } +else + store_reset(result->s + result->ptr + 1); /* Get here by goto from various error checks. */ - IBASE_EXIT: +IBASE_EXIT: - if (stmth != NULL) - isc_dsql_free_statement(status, &stmth, DSQL_drop); +if (stmth) + isc_dsql_free_statement(status, &stmth, DSQL_drop); /* Non-NULL result indicates a successful result */ - if (result != NULL) { - *resultptr = result; - return OK; - } else { - DEBUG(D_lookup) debug_printf("%s\n", *errmsg); - return yield; /* FAIL or DEFER */ - } +if (result) + { + *resultptr = string_from_gstring(result); + return OK; + } +else + { + DEBUG(D_lookup) debug_printf("%s\n", *errmsg); + return yield; /* FAIL or DEFER */ + } } diff --git a/src/src/lookups/ldap.c b/src/src/lookups/ldap.c index b52ef2221..8d6ac2674 100644 --- a/src/src/lookups/ldap.c +++ b/src/src/lookups/ldap.c @@ -145,7 +145,7 @@ struct timeval *timeoutptr = NULL; uschar *attr; uschar **attrp; -uschar *data = NULL; +gstring * data = NULL; uschar *dn = NULL; uschar *host; uschar **values; @@ -161,9 +161,7 @@ int error_yield = DEFER; int msgid; int rc, ldap_rc, ldap_parse_rc; int port; -int ptr = 0; int rescount = 0; -int size = 0; BOOL attribute_found = FALSE; BOOL ldapi = FALSE; @@ -722,7 +720,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == DEBUG(D_lookup) debug_printf("LDAP result loop\n"); for(e = ldap_first_entry(lcp->ld, result), valuecount = 0; - e != NULL; + e; e = ldap_next_entry(lcp->ld, e)) { uschar *new_dn; @@ -734,7 +732,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == /* Results for multiple entries values are separated by newlines. */ - if (data != NULL) data = string_catn(data, &size, &ptr, US"\n", 1); + if (data) data = string_catn(data, US"\n", 1); /* Get the DN from the last result. */ @@ -762,8 +760,8 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == { /* condition, because of the else */ if (new_dn != NULL) /* below, that's for the first only */ { - data = string_cat(data, &size, &ptr, new_dn); - data[ptr] = 0; + data = string_cat(data, new_dn); + (void) string_from_gstring(data); attribute_found = TRUE; } } @@ -776,8 +774,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == If there are multiple values, they are given within the quotes, comma separated. */ else for (attr = US ldap_first_attribute(lcp->ld, e, &ber); - attr != NULL; - attr = US ldap_next_attribute(lcp->ld, e, ber)) + attr; attr = US ldap_next_attribute(lcp->ld, e, ber)) { DEBUG(D_lookup) debug_printf("LDAP attr loop\n"); @@ -789,21 +786,20 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == { /* Get array of values for this attribute. */ - if ((firstval = values = USS ldap_get_values(lcp->ld, e, CS attr)) - != NULL) + if ((firstval = values = USS ldap_get_values(lcp->ld, e, CS attr))) { if (attrs_requested != 1) { if (insert_space) - data = string_catn(data, &size, &ptr, US" ", 1); + data = string_catn(data, US" ", 1); else insert_space = TRUE; - data = string_cat(data, &size, &ptr, attr); - data = string_catn(data, &size, &ptr, US"=\"", 2); + data = string_cat(data, attr); + data = string_catn(data, US"=\"", 2); } - while (*values != NULL) + while (*values) { uschar *value = *values; int len = Ustrlen(value); @@ -818,7 +814,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == attribute and append only every non first value. */ if (data && valuecount > 1) - data = string_catn(data, &size, &ptr, US",", 1); + data = string_catn(data, US",", 1); /* For multiple attributes, the data is in quotes. We must escape internal quotes, backslashes, newlines, and must double commas. */ @@ -829,14 +825,14 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == for (j = 0; j < len; j++) { if (value[j] == '\n') - data = string_catn(data, &size, &ptr, US"\\n", 2); + data = string_catn(data, US"\\n", 2); else if (value[j] == ',') - data = string_catn(data, &size, &ptr, US",,", 2); + data = string_catn(data, US",,", 2); else { if (value[j] == '\"' || value[j] == '\\') - data = string_catn(data, &size, &ptr, US"\\", 1); - data = string_catn(data, &size, &ptr, value+j, 1); + data = string_catn(data, US"\\", 1); + data = string_catn(data, value+j, 1); } } } @@ -848,9 +844,9 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == int j; for (j = 0; j < len; j++) if (value[j] == ',') - data = string_catn(data, &size, &ptr, US",,", 2); + data = string_catn(data, US",,", 2); else - data = string_catn(data, &size, &ptr, value+j, 1); + data = string_catn(data, value+j, 1); } @@ -863,7 +859,7 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == /* Closing quote at the end of the data for a named attribute. */ if (attrs_requested != 1) - data = string_catn(data, &size, &ptr, US"\"", 1); + data = string_catn(data, US"\"", 1); /* Free the values */ @@ -890,15 +886,15 @@ while ((rc = ldap_result(lcp->ld, msgid, 0, timeoutptr, &result)) == /* Terminate the dynamic string that we have built and reclaim unused store */ -if (data != NULL) +if (data) { - data[ptr] = 0; - store_reset(data + ptr + 1); + (void) string_from_gstring(data); + store_reset(data->s + data->ptr + 1); } /* Copy the last dn into eldap_dn */ -if (dn != NULL) +if (dn) { eldap_dn = string_copy(dn); #if defined LDAP_LIB_NETSCAPE || defined LDAP_LIB_OPENLDAP2 @@ -1077,8 +1073,8 @@ if (!attribute_found) /* Otherwise, it's all worked */ -DEBUG(D_lookup) debug_printf("LDAP search: returning: %s\n", data); -*res = data; +DEBUG(D_lookup) debug_printf("LDAP search: returning: %s\n", data->s); +*res = data->s; RETURN_OK: if (result != NULL) ldap_msgfree(result); diff --git a/src/src/lookups/lf_functions.h b/src/src/lookups/lf_functions.h index d2487d362..210aae4d5 100644 --- a/src/src/lookups/lf_functions.h +++ b/src/src/lookups/lf_functions.h @@ -9,7 +9,7 @@ extern int lf_check_file(int, uschar *, int, int, uid_t *, gid_t *, const char *, uschar **); -extern uschar *lf_quote(uschar *, uschar *, int, uschar *, int *, int *); +extern gstring *lf_quote(uschar *, uschar *, int, gstring *); extern int lf_sqlperform(const uschar *, const uschar *, const uschar *, const uschar *, uschar **, uschar **, uint *, int(*)(const uschar *, uschar *, uschar **, diff --git a/src/src/lookups/lf_quote.c b/src/src/lookups/lf_quote.c index 2a76756e9..1541d0d16 100644 --- a/src/src/lookups/lf_quote.c +++ b/src/src/lookups/lf_quote.c @@ -22,18 +22,15 @@ Arguments: name the field name value the data value vlength the data length - result the result pointer - asize points to the size variable - aoffset points to the offset variable + result the result expanding-string Returns: the result pointer (possibly updated) */ -uschar * -lf_quote(uschar *name, uschar *value, int vlength, uschar *result, int *asize, - int *aoffset) +gstring * +lf_quote(uschar *name, uschar *value, int vlength, gstring * result) { -result = string_append(result, asize, aoffset, 2, name, US"="); +result = string_append(result, 2, name, US"="); /* NULL is handled as an empty string */ @@ -49,19 +46,19 @@ character. */ if (value[0] == 0 || Ustrpbrk(value, " \t\n\r") != NULL || value[0] == '\"') { int j; - result = string_catn(result, asize, aoffset, US"\"", 1); + result = string_catn(result, US"\"", 1); for (j = 0; j < vlength; j++) { if (value[j] == '\"' || value[j] == '\\') - result = string_catn(result, asize, aoffset, US"\\", 1); - result = string_catn(result, asize, aoffset, US value+j, 1); + result = string_catn(result, US"\\", 1); + result = string_catn(result, US value+j, 1); } - result = string_catn(result, asize, aoffset, US"\"", 1); + result = string_catn(result, US"\"", 1); } else - result = string_catn(result, asize, aoffset, US value, vlength); + result = string_catn(result, US value, vlength); -return string_catn(result, asize, aoffset, US" ", 1); +return string_catn(result, US" ", 1); } /* End of lf_quote.c */ diff --git a/src/src/lookups/lsearch.c b/src/src/lookups/lsearch.c index 6101d00ac..745856d02 100644 --- a/src/src/lookups/lsearch.c +++ b/src/src/lookups/lsearch.c @@ -101,11 +101,10 @@ for (last_was_eol = TRUE; Ufgets(buffer, sizeof(buffer), f) != NULL; last_was_eol = this_is_eol) { - int ptr, size; int p = Ustrlen(buffer); int linekeylength; BOOL this_is_comment; - uschar *yield; + gstring * yield; uschar *s = buffer; /* Check whether this the final segment of a line. If it follows an @@ -240,7 +239,7 @@ for (last_was_eol = TRUE; /* Reset dynamic store, if we need to, and revert to the search pool */ - if (reset_point != NULL) + if (reset_point) { store_reset(reset_point); store_pool = old_pool; @@ -254,11 +253,9 @@ for (last_was_eol = TRUE; Initialize, and copy the first segment of data. */ this_is_comment = FALSE; - size = 100; - ptr = 0; - yield = store_get(size); + yield = string_get(100); if (*s != 0) - yield = string_cat(yield, &size, &ptr, s); + yield = string_cat(yield, s); /* Now handle continuations */ @@ -294,18 +291,17 @@ for (last_was_eol = TRUE; /* Join a physical or logical line continuation onto the result string. */ - yield = string_cat(yield, &size, &ptr, s); + yield = string_cat(yield, s); } - yield[ptr] = 0; - store_reset(yield + ptr + 1); - *result = yield; + store_reset(yield->s + yield->ptr + 1); + *result = string_from_gstring(yield); return OK; } /* Reset dynamic store, if we need to */ -if (reset_point != NULL) +if (reset_point) { store_reset(reset_point); store_pool = old_pool; diff --git a/src/src/lookups/mysql.c b/src/src/lookups/mysql.c index b5133bc00..0d3d92aa8 100644 --- a/src/src/lookups/mysql.c +++ b/src/src/lookups/mysql.c @@ -140,11 +140,9 @@ MYSQL_ROW mysql_row_data; MYSQL_FIELD *fields; int i; -int ssize = 0; -int offset = 0; int yield = DEFER; unsigned int num_fields; -uschar *result = NULL; +gstring * result = NULL; mysql_connection *cn; uschar *server_copy = NULL; uschar *sdata[4]; @@ -288,7 +286,8 @@ if ((mysql_result = mysql_use_result(mysql_handle)) == NULL) if ( mysql_field_count(mysql_handle) == 0 ) { DEBUG(D_lookup) debug_printf("MYSQL: query was not one that returns data\n"); - result = string_sprintf("%d", mysql_affected_rows(mysql_handle)); + result = string_cat(result, + string_sprintf("%d", mysql_affected_rows(mysql_handle))); *do_cache = 0; goto MYSQL_EXIT; } @@ -308,25 +307,25 @@ row, we insert '\n' between them. */ fields = mysql_fetch_fields(mysql_result); -while ((mysql_row_data = mysql_fetch_row(mysql_result)) != NULL) +while ((mysql_row_data = mysql_fetch_row(mysql_result))) { unsigned long *lengths = mysql_fetch_lengths(mysql_result); - if (result != NULL) - result = string_catn(result, &ssize, &offset, US"\n", 1); + if (result) + result = string_catn(result, US"\n", 1); if (num_fields == 1) { if (mysql_row_data[0] != NULL) /* NULL value yields nothing */ - result = string_catn(result, &ssize, &offset, US mysql_row_data[0], + { + result = string_catn(result, US mysql_row_data[0], lengths[0]); + (void) string_from_gstring(result); + } } else for (i = 0; i < num_fields; i++) - { - result = lf_quote(US fields[i].name, US mysql_row_data[i], lengths[i], - result, &ssize, &offset); - } + result = lf_quote(US fields[i].name, US mysql_row_data[i], lengths[i], result); } /* more results? -1 = no, >0 = error, 0 = yes (keep looping) @@ -348,15 +347,15 @@ while((i = mysql_next_result(mysql_handle)) >= 0) { Otherwise, we must terminate the string which has been built; string_cat() always leaves enough room for a terminating zero. */ -if (result == NULL) +if (!result) { yield = FAIL; *errmsg = US"MYSQL: no data found"; } else { - result[offset] = 0; - store_reset(result + offset + 1); + (void) string_from_gstring(result); + store_reset(result->s + result->ptr + 1); } /* Get here by goto from various error checks and from the case where no data @@ -367,13 +366,13 @@ MYSQL_EXIT: /* Free mysal store for any result that was got; don't close the connection, as it is cached. */ -if (mysql_result != NULL) mysql_free_result(mysql_result); +if (mysql_result) mysql_free_result(mysql_result); /* Non-NULL result indicates a successful result */ -if (result != NULL) +if (result) { - *resultptr = result; + *resultptr = result->s; return OK; } else diff --git a/src/src/lookups/nisplus.c b/src/src/lookups/nisplus.c index ff632a1ca..03c343103 100644 --- a/src/src/lookups/nisplus.c +++ b/src/src/lookups/nisplus.c @@ -46,8 +46,6 @@ nisplus_find(void *handle, uschar *filename, uschar *query, int length, uschar **result, uschar **errmsg, uint *do_cache) { int i; -int ssize = 0; -int offset = 0; int error_error = FAIL; uschar *field_name = NULL; nis_result *nrt = NULL; @@ -57,6 +55,7 @@ struct entry_obj *eo; struct table_obj *ta; uschar *p = query + length; uschar *yield = NULL; +gstring * yield = NULL; do_cache = do_cache; /* Placate picky compilers */ @@ -156,33 +155,34 @@ for (i = 0; i < eo->en_cols.en_cols_len; i++) if (field_name == NULL) { - yield = string_cat(yield, &ssize, &offset,US tc->tc_name); - yield = string_catn(yield, &ssize, &offset, US"=", 1); + yield = string_cat (yield, tc->tc_name); + yield = string_catn(yield, US"=", 1); /* Quote the value if it contains spaces or is empty */ if (value[0] == 0 || Ustrchr(value, ' ') != NULL) { int j; - yield = string_catn(yield, &ssize, &offset, US"\"", 1); + yield = string_catn(yield, US"\"", 1); for (j = 0; j < len; j++) { if (value[j] == '\"' || value[j] == '\\') - yield = string_catn(yield, &ssize, &offset, US"\\", 1); - yield = string_catn(yield, &ssize, &offset, value+j, 1); + yield = string_catn(yield, US"\\", 1); + yield = string_catn(yield, value+j, 1); } - yield = string_catn(yield, &ssize, &offset, US"\"", 1); + yield = string_catn(yield, US"\"", 1); } - else yield = string_catn(yield, &ssize, &offset, value, len); + else + eyield = string_catn(yield, value, len); - yield = string_catn(yield, &ssize, &offset, US" ", 1); + yield = string_catn(yield, US" ", 1); } /* When the specified field is found, grab its data and finish */ else if (Ustrcmp(field_name, tc->tc_name) == 0) { - yield = string_copyn(value, len); + yield = string_catn(yield, value, len); goto NISPLUS_EXIT; } } @@ -190,26 +190,23 @@ for (i = 0; i < eo->en_cols.en_cols_len; i++) /* Error if a field name was specified and we didn't find it; if no field name, ensure the concatenated data is zero-terminated. */ -if (field_name != NULL) +if (field_name) *errmsg = string_sprintf("NIS+ field %s not found for %s", field_name, query); else - { - yield[offset] = 0; - store_reset(yield + offset + 1); - } + store_reset(yield->s + yield->ptr + 1); /* Restore the colon in the query, and free result store before finishing. */ NISPLUS_EXIT: -if (field_name != NULL) field_name[-1] = ':'; -if (nrt != NULL) nis_freeresult(nrt); -if (nre != NULL) nis_freeresult(nre); +if (field_name) field_name[-1] = ':'; +if (nrt) nis_freeresult(nrt); +if (nre) nis_freeresult(nre); -if (yield != NULL) +if (yield) { - *result = yield; + *result = string_from_gstring(yield); return OK; } diff --git a/src/src/lookups/oracle.c b/src/src/lookups/oracle.c index eca15f1b4..bc14def70 100644 --- a/src/src/lookups/oracle.c +++ b/src/src/lookups/oracle.c @@ -255,15 +255,12 @@ Ora_Define *def = NULL; void *hda = NULL; int i; -int ssize = 0; -int offset = 0; int yield = DEFER; unsigned int num_fields = 0; -uschar *result = NULL; +gstring * result = NULL; oracle_connection *cn = NULL; uschar *server_copy = NULL; uschar *sdata[4]; -uschar tmp[1024]; /* Disaggregate the parameters from the server argument. The order is host, database, user, password. We can write to the string, since it is in a @@ -292,19 +289,17 @@ if (sdata[1][0] == 0) sdata[1] = NULL; /* See if we have a cached connection to the server */ -for (cn = oracle_connections; cn != NULL; cn = cn->next) - { +for (cn = oracle_connections; cn; cn = cn->next) if (strcmp(cn->server, server_copy) == 0) { oracle_handle = cn->handle; hda = cn->hda_mem; break; } - } /* If no cached connection, we must set one up */ -if (cn == NULL) +if (!cn) { DEBUG(D_lookup) debug_printf("ORACLE new connection: host=%s database=%s " "user=%s\n", sdata[0], sdata[1], sdata[2]); @@ -400,12 +395,12 @@ while (cda->rc != NO_DATA_FOUND) /* Loop for each row */ ofetch(cda); if(cda->rc == NO_DATA_FOUND) break; - if (result) result = string_catn(result, &ssize, &offset, "\n", 1); + if (result) result = string_catn(result, "\n", 1); /* Single field - just add on the data */ if (num_fields == 1) - result = string_catn(result, &ssize, &offset, def[0].buf, def[0].col_retlen); + result = string_catn(result, def[0].buf, def[0].col_retlen); /* Multiple fields - precede by file name, removing {lead,trail}ing WS */ @@ -417,8 +412,8 @@ while (cda->rc != NO_DATA_FOUND) /* Loop for each row */ while (*s != 0 && isspace(*s)) s++; slen = Ustrlen(s); while (slen > 0 && isspace(s[slen-1])) slen--; - result = string_catn(result, &ssize, &offset, s, slen); - result = string_catn(result, &ssize, &offset, US"=", 1); + result = string_catn(result, s, slen); + result = string_catn(result, US"=", 1); /* int and float type wont ever need escaping. Otherwise, quote the value if it contains spaces or is empty. */ @@ -427,41 +422,38 @@ while (cda->rc != NO_DATA_FOUND) /* Loop for each row */ (def[i].buf[0] == 0 || strchr(def[i].buf, ' ') != NULL)) { int j; - result = string_catn(result, &ssize, &offset, "\"", 1); + result = string_catn(result, "\"", 1); for (j = 0; j < def[i].col_retlen; j++) { if (def[i].buf[j] == '\"' || def[i].buf[j] == '\\') - result = string_catn(result, &ssize, &offset, "\\", 1); - result = string_catn(result, &ssize, &offset, def[i].buf+j, 1); + result = string_catn(result, "\\", 1); + result = string_catn(result, def[i].buf+j, 1); } - result = string_catn(result, &ssize, &offset, "\"", 1); + result = string_catn(result, "\"", 1); } else switch(desc[i].dbtype) { case INT_TYPE: - sprintf(CS tmp, "%d", def[i].int_buf); - result = string_cat(result, &ssize, &offset, tmp); - break; + result = string_cat(result, string_sprintf("%d", def[i].int_buf)); + break; case FLOAT_TYPE: - sprintf(CS tmp, "%f", def[i].flt_buf); - result = string_cat(result, &ssize, &offset, tmp); - break; + result = string_cat(result, string_sprintf("%f", def[i].flt_buf)); + break; case STRING_TYPE: - result = string_catn(result, &ssize, &offset, def[i].buf, - def[i].col_retlen); - break; + result = string_catn(result, def[i].buf, def[i].col_retlen); + break; default: - *errmsg = string_sprintf("ORACLE: unknown field type %d", desc[i].dbtype); - *defer_break = FALSE; - result = NULL; - goto ORACLE_EXIT; + *errmsg = string_sprintf("ORACLE: unknown field type %d", desc[i].dbtype); + *defer_break = FALSE; + result = NULL; + goto ORACLE_EXIT; } - result = string_catn(result, &ssize, &offset, " ", 1); + result = string_catn(result, " ", 1); } } @@ -469,16 +461,13 @@ while (cda->rc != NO_DATA_FOUND) /* Loop for each row */ Otherwise, we must terminate the string which has been built; string_cat() always leaves enough room for a terminating zero. */ -if (result == NULL) +if (!result) { yield = FAIL; *errmsg = "ORACLE: no data found"; } else - { - result[offset] = 0; - store_reset(result + offset + 1); - } + store_reset(result->s + result->ptr + 1); /* Get here by goto from various error checks. */ @@ -492,9 +481,9 @@ ORACLE_EXIT_NO_VALS: /* Non-NULL result indicates a successful result */ -if (result != NULL) +if (result) { - *resultptr = result; + *resultptr = string_from_gstring(result); return OK; } else diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c index d71f97b33..ef8f0997d 100644 --- a/src/src/lookups/pgsql.c +++ b/src/src/lookups/pgsql.c @@ -125,9 +125,7 @@ PGconn *pg_conn = NULL; PGresult *pg_result = NULL; int i; -uschar *result = NULL; -int ssize = 0; -int offset = 0; +gstring * result = NULL; int yield = DEFER; unsigned int num_fields, num_tuples; pgsql_connection *cn; @@ -287,30 +285,31 @@ else { case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: - /* The command was successful but did not return any data since it was - * not SELECT but either an INSERT, UPDATE or DELETE statement. Tell the - * high level code to not cache this query, and clean the current cache for - * this handle by setting *do_cache zero. */ - result = string_copy(US PQcmdTuples(pg_result)); - offset = Ustrlen(result); - *do_cache = 0; - DEBUG(D_lookup) debug_printf("PGSQL: command does not return any data " - "but was successful. Rows affected: %s\n", result); + /* The command was successful but did not return any data since it was + not SELECT but either an INSERT, UPDATE or DELETE statement. Tell the + high level code to not cache this query, and clean the current cache for + this handle by setting *do_cache zero. */ + + result = string_cat(result, US PQcmdTuples(pg_result)); + *do_cache = 0; + DEBUG(D_lookup) debug_printf("PGSQL: command does not return any data " + "but was successful. Rows affected: %s\n", result->s); + break; case PGRES_TUPLES_OK: - break; + break; default: - /* This was the original code: - *errmsg = string_sprintf("PGSQL: query failed: %s\n", - PQresultErrorMessage(pg_result)); - This was suggested by a user: - */ + /* This was the original code: + *errmsg = string_sprintf("PGSQL: query failed: %s\n", + PQresultErrorMessage(pg_result)); + This was suggested by a user: + */ - *errmsg = string_sprintf("PGSQL: query failed: %s (%s) (%s)\n", + *errmsg = string_sprintf("PGSQL: query failed: %s (%s) (%s)\n", PQresultErrorMessage(pg_result), PQresStatus(PQresultStatus(pg_result)), query); - goto PGSQL_EXIT; + goto PGSQL_EXIT; } /* Result is in pg_result. Find the number of fields returned. If this is one, @@ -326,23 +325,19 @@ row, we insert '\n' between them. */ for (i = 0; i < num_tuples; i++) { - if (result != NULL) - result = string_catn(result, &ssize, &offset, US"\n", 1); - - if (num_fields == 1) - { - result = string_catn(result, &ssize, &offset, - US PQgetvalue(pg_result, i, 0), PQgetlength(pg_result, i, 0)); - } + if (result) + result = string_catn(result, US"\n", 1); - else + if (num_fields == 1) + result = string_catn(NULL, + US PQgetvalue(pg_result, i, 0), PQgetlength(pg_result, i, 0)); + else { int j; for (j = 0; j < num_fields; j++) { uschar *tmp = US PQgetvalue(pg_result, i, j); - result = lf_quote(US PQfname(pg_result, j), tmp, Ustrlen(tmp), result, - &ssize, &offset); + result = lf_quote(US PQfname(pg_result, j), tmp, Ustrlen(tmp), result); } } } @@ -351,16 +346,13 @@ for (i = 0; i < num_tuples; i++) Otherwise, we must terminate the string which has been built; string_cat() always leaves enough room for a terminating zero. */ -if (result == NULL) +if (!result) { yield = FAIL; *errmsg = US"PGSQL: no data found"; } else - { - result[offset] = 0; - store_reset(result + offset + 1); - } + store_reset(result->s + result->ptr + 1); /* Get here by goto from various error checks. */ @@ -369,13 +361,13 @@ PGSQL_EXIT: /* Free store for any result that was got; don't close the connection, as it is cached. */ -if (pg_result != NULL) PQclear(pg_result); +if (pg_result) PQclear(pg_result); /* Non-NULL result indicates a successful result */ -if (result != NULL) +if (result) { - *resultptr = result; + *resultptr = string_from_gstring(result); return OK; } else diff --git a/src/src/lookups/redis.c b/src/src/lookups/redis.c index 3a96f5ef9..e8989ca3a 100644 --- a/src/src/lookups/redis.c +++ b/src/src/lookups/redis.c @@ -80,13 +80,10 @@ redisReply *redis_reply = NULL; redisReply *entry = NULL; redisReply *tentry = NULL; redis_connection *cn; -int ssize = 0; -int offset = 0; int yield = DEFER; int i, j; -uschar *result = NULL; +gstring * result = NULL; uschar *server_copy = NULL; -uschar *tmp, *ttmp; uschar *sdata[3]; /* Disaggregate the parameters from the server argument. @@ -217,10 +214,13 @@ if(sdata[1]) for (i = 0; *s && i < nele(argv); i++) { - for (argv[i] = NULL, siz = ptr = 0; (c = *s) && !isspace(c); s++) + gstring * g; + + for (g = NULL; (c = *s) && !isspace(c); s++) if (c != '\\' || *++s) /* backslash protects next char */ - argv[i] = string_catn(argv[i], &siz, &ptr, s, 1); - *(argv[i]+ptr) = '\0'; + g = string_catn(g, s, 1); + argv[i] = string_from_gstring(g); + DEBUG(D_lookup) debug_printf("REDIS: argv[%d] '%s'\n", i, argv[i]); while (isspace(*s)) s++; } @@ -249,20 +249,18 @@ switch (redis_reply->type) case REDIS_REPLY_NIL: DEBUG(D_lookup) debug_printf("REDIS: query was not one that returned any data\n"); - result = string_sprintf(""); + result = string_catn(result, US"", 1); *do_cache = 0; goto REDIS_EXIT; /* NOTREACHED */ case REDIS_REPLY_INTEGER: - ttmp = (redis_reply->integer != 0) ? US"true" : US"false"; - result = string_cat(result, &ssize, &offset, US ttmp); + result = string_cat(result, redis_reply->integer != 0 ? US"true" : US"false"); break; case REDIS_REPLY_STRING: case REDIS_REPLY_STATUS: - result = string_catn(result, &ssize, &offset, - US redis_reply->str, redis_reply->len); + result = string_catn(result, US redis_reply->str, redis_reply->len); break; case REDIS_REPLY_ARRAY: @@ -275,17 +273,15 @@ switch (redis_reply->type) entry = redis_reply->element[i]; if (result) - result = string_catn(result, &ssize, &offset, US"\n", 1); + result = string_catn(result, US"\n", 1); switch (entry->type) { case REDIS_REPLY_INTEGER: - tmp = string_sprintf("%d", entry->integer); - result = string_cat(result, &ssize, &offset, US tmp); + result = string_cat(result, string_sprintf("%d", entry->integer)); break; case REDIS_REPLY_STRING: - result = string_catn(result, &ssize, &offset, - US entry->str, entry->len); + result = string_catn(result, US entry->str, entry->len); break; case REDIS_REPLY_ARRAY: for (j = 0; j < entry->elements; j++) @@ -293,17 +289,15 @@ switch (redis_reply->type) tentry = entry->element[j]; if (result) - result = string_catn(result, &ssize, &offset, US"\n", 1); + result = string_catn(result, US"\n", 1); switch (tentry->type) { case REDIS_REPLY_INTEGER: - ttmp = string_sprintf("%d", tentry->integer); - result = string_cat(result, &ssize, &offset, US ttmp); + result = string_cat(result, string_sprintf("%d", tentry->integer)); break; case REDIS_REPLY_STRING: - result = string_catn(result, &ssize, &offset, - US tentry->str, tentry->len); + result = string_catn(result, US tentry->str, tentry->len); break; case REDIS_REPLY_ARRAY: DEBUG(D_lookup) @@ -327,10 +321,7 @@ switch (redis_reply->type) if (result) - { - result[offset] = 0; - store_reset(result + offset + 1); - } + store_reset(result->s + result->ptr + 1); else { yield = FAIL; @@ -348,7 +339,7 @@ if (redis_reply) freeReplyObject(redis_reply); if (result) { - *resultptr = result; + *resultptr = string_from_gstring(result); return OK; } else diff --git a/src/src/lookups/sqlite.c b/src/src/lookups/sqlite.c index 0b01fdbce..0df853736 100644 --- a/src/src/lookups/sqlite.c +++ b/src/src/lookups/sqlite.c @@ -41,21 +41,16 @@ return db; /* See local README for interface description. */ -struct strbuf { - uschar *string; - int size; - int len; -}; - -static int sqlite_callback(void *arg, int argc, char **argv, char **azColName) +static int +sqlite_callback(void *arg, int argc, char **argv, char **azColName) { -struct strbuf *res = arg; +gstring * res = *(gstring **)arg; int i; /* For second and subsequent results, insert \n */ -if (res->string != NULL) - res->string = string_catn(res->string, &res->size, &res->len, US"\n", 1); +if (res) + res = string_catn(res, US"\n", 1); if (argc > 1) { @@ -63,18 +58,14 @@ if (argc > 1) for (i = 0; i < argc; i++) { uschar *value = US((argv[i] != NULL)? argv[i]:"<NULL>"); - res->string = lf_quote(US azColName[i], value, Ustrlen(value), res->string, - &res->size, &res->len); + res = lf_quote(US azColName[i], value, Ustrlen(value), res); } } else - { - res->string = string_append(res->string, &res->size, &res->len, 1, - (argv[0] != NULL)? argv[0]:"<NULL>"); - } + res = string_cat(res, argv[0] ? US argv[0] : US "<NULL>"); -res->string[res->len] = 0; +*(gstring **)arg = res; return 0; } @@ -84,7 +75,7 @@ sqlite_find(void *handle, uschar *filename, const uschar *query, int length, uschar **result, uschar **errmsg, uint *do_cache) { int ret; -struct strbuf res = { NULL, 0, 0 }; +gstring * res = NULL; ret = sqlite3_exec(handle, CS query, sqlite_callback, &res, (char **)errmsg); if (ret != SQLITE_OK) @@ -93,9 +84,9 @@ if (ret != SQLITE_OK) return FAIL; } -if (res.string == NULL) *do_cache = 0; +if (!res) *do_cache = 0; -*result = res.string; +*result = string_from_gstring(res); return OK; } |