diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 42c95520f4..ae8e3747e1 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -4,7 +4,7 @@ * * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.74.2.1 2007/07/02 21:58:38 mha Exp $ + * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.74.2.2 2008/02/20 22:18:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,8 +44,6 @@ int optreset; typedef long pgpid_t; -#define WHITESPACE "\f\n\r\t\v" /* as defined by isspace() */ - /* postgres version ident string */ #define PM_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n" @@ -405,33 +403,52 @@ test_postmaster_connection(bool do_checkpoint) int i; char portstr[32]; char *p; + char *q; char connstr[128]; /* Should be way more than enough! */ *portstr = '\0'; - /* post_opts */ + /* + * Look in post_opts for a -p switch. + * + * This parsing code is not amazingly bright; it could for instance + * get fooled if ' -p' occurs within a quoted argument value. Given + * that few people pass complicated settings in post_opts, it's + * probably good enough. + */ for (p = post_opts; *p;) { - /* advance past whitespace/quoting */ - while (isspace((unsigned char) *p) || *p == '\'' || *p == '"') + /* advance past whitespace */ + while (isspace((unsigned char) *p)) p++; - if (strncmp(p, "-p", strlen("-p")) == 0) + if (strncmp(p, "-p", 2) == 0) { - p += strlen("-p"); - /* advance past whitespace/quoting */ + p += 2; + /* advance past any whitespace/quoting */ while (isspace((unsigned char) *p) || *p == '\'' || *p == '"') p++; - StrNCpy(portstr, p, Min(strcspn(p, "\"'" WHITESPACE) + 1, - sizeof(portstr))); + /* find end of value (not including any ending quote!) */ + q = p; + while (*q && + !(isspace((unsigned char) *q) || *q == '\'' || *q == '"')) + q++; + /* and save the argument value */ + StrNCpy(portstr, p, Min((q - p) + 1, sizeof(portstr))); /* keep looking, maybe there is another -p */ + p = q; } /* Advance to next whitespace */ while (*p && !isspace((unsigned char) *p)) p++; } - /* config file */ + /* + * Search config file for a 'port' option. + * + * This parsing code isn't amazingly bright either, but it should be + * okay for valid port settings. + */ if (!*portstr) { char **optlines; @@ -445,28 +462,35 @@ test_postmaster_connection(bool do_checkpoint) while (isspace((unsigned char) *p)) p++; - if (strncmp(p, "port", strlen("port")) != 0) + if (strncmp(p, "port", 4) != 0) continue; - p += strlen("port"); + p += 4; while (isspace((unsigned char) *p)) p++; if (*p != '=') continue; p++; - while (isspace((unsigned char) *p)) + /* advance past any whitespace/quoting */ + while (isspace((unsigned char) *p) || *p == '\'' || *p == '"') p++; - StrNCpy(portstr, p, Min(strcspn(p, "#" WHITESPACE) + 1, - sizeof(portstr))); + /* find end of value (not including any ending quote/comment!) */ + q = p; + while (*q && + !(isspace((unsigned char) *q) || + *q == '\'' || *q == '"' || *q == '#')) + q++; + /* and save the argument value */ + StrNCpy(portstr, p, Min((q - p) + 1, sizeof(portstr))); /* keep looking, maybe there is another */ } } } - /* environment */ + /* Check environment */ if (!*portstr && getenv("PGPORT") != NULL) StrNCpy(portstr, getenv("PGPORT"), sizeof(portstr)); - /* default */ + /* Else use compiled-in default */ if (!*portstr) snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);