コード例 #1
0
ファイル: server.c プロジェクト: 0x0FFF/postgres
/*
 * check_pghost_envvar()
 *
 * Tests that PGHOST does not point to a non-local server
 */
void
check_pghost_envvar(void)
{
	PQconninfoOption *option;
	PQconninfoOption *start;

	/* Get valid libpq env vars from the PQconndefaults function */

	start = PQconndefaults();

	if (!start)
		pg_fatal("out of memory\n");

	for (option = start; option->keyword != NULL; option++)
	{
		if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
							   strcmp(option->envvar, "PGHOSTADDR") == 0))
		{
			const char *value = getenv(option->envvar);

			if (value && strlen(value) > 0 &&
			/* check for 'local' host values */
				(strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
				 strcmp(value, "::1") != 0 && value[0] != '/'))
				pg_fatal("libpq environment variable %s has a non-local server value: %s\n",
						 option->envvar, value);
		}
	}

	/* Free the memory that libpq allocated on our behalf */
	PQconninfoFree(start);
}
コード例 #2
0
ファイル: connection_type.c プロジェクト: gencer/psycopg2
static PyObject *
psyco_conn_get_dsn_parameters(connectionObject *self)
{
#if PG_VERSION_NUM >= 90300
    PyObject *res = NULL;
    PQconninfoOption *options = NULL;

    EXC_IF_CONN_CLOSED(self);

    if (!(options = PQconninfo(self->pgconn))) {
        PyErr_NoMemory();
        goto exit;
    }

    res = psycopg_dict_from_conninfo_options(options, /* include_password = */ 0);

exit:
    PQconninfoFree(options);

    return res;
#else
    PyErr_SetString(NotSupportedError, "PQconninfo not available in libpq < 9.3");
    return NULL;
#endif
}
コード例 #3
0
ファイル: server.c プロジェクト: agentm/postgres
/*
 * check_for_libpq_envvars()
 *
 * tests whether any libpq environment variables are set.
 * Since pg_upgrade connects to both the old and the new server,
 * it is potentially dangerous to have any of these set.
 *
 * If any are found, will log them and cancel.
 */
void
check_for_libpq_envvars(void)
{
	PQconninfoOption *option;
	PQconninfoOption *start;
	bool		found = false;

	/* Get valid libpq env vars from the PQconndefaults function */

	start = option = PQconndefaults();

	while (option->keyword != NULL)
	{
		const char *value;

		if (option->envvar && (value = getenv(option->envvar)) && strlen(value) > 0)
		{
			found = true;

			pg_log(PG_WARNING,
				   "libpq env var %-20s is currently set to: %s\n", option->envvar, value);
		}

		option++;
	}

	/* Free the memory that libpq allocated on our behalf */
	PQconninfoFree(start);

	if (found)
		pg_log(PG_FATAL,
			   "libpq env vars have been found and listed above, please unset them for pg_upgrade\n");
}
コード例 #4
0
ファイル: pgtclCmds.c プロジェクト: sunyangkobe/cscd43
int
Pg_conndefaults(ClientData cData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
	PQconninfoOption *options = PQconndefaults();
	PQconninfoOption *option;
	Tcl_DString result;
	char		ibuf[32];

	if (options)
	{
		Tcl_DStringInit(&result);

		for (option = options; option->keyword != NULL; option++)
		{
			char	   *val = option->val ? option->val : "";

			sprintf(ibuf, "%d", option->dispsize);
			Tcl_DStringStartSublist(&result);
			Tcl_DStringAppendElement(&result, option->keyword);
			Tcl_DStringAppendElement(&result, option->label);
			Tcl_DStringAppendElement(&result, option->dispchar);
			Tcl_DStringAppendElement(&result, ibuf);
			Tcl_DStringAppendElement(&result, val);
			Tcl_DStringEndSublist(&result);
		}
		Tcl_DStringResult(interp, &result);

		PQconninfoFree(options);
	}

	return TCL_OK;
}
コード例 #5
0
ファイル: pgConn.cpp プロジェクト: AnnaSkawinska/pgadmin3
void pgConn::ExamineLibpqVersion()
{
	libpqVersion = 7.3;
	PQconninfoOption *cio = PQconndefaults();

	if (cio)
	{
		PQconninfoOption *co = cio;
		while (co->keyword)
		{
			if (!strcmp(co->keyword, "sslmode"))
			{
				if (libpqVersion < 7.4)
					libpqVersion = 7.4;
			}
			if (!strcmp(co->keyword, "sslrootcert"))
			{
				if (libpqVersion < 8.4)
					libpqVersion = 8.4;
			}
			if (!strcmp(co->keyword, "sslcompression"))
			{
				if (libpqVersion < 9.2)
					libpqVersion = 9.2;
			}
			co++;
		}
		PQconninfoFree(cio);
	}
}
コード例 #6
0
static PyObject *
psyco_parse_dsn(PyObject *self, PyObject *args, PyObject *kwargs)
{
    char *err = NULL;
    PQconninfoOption *options = NULL;
    PyObject *res = NULL, *dsn;

    static char *kwlist[] = {"dsn", NULL};
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &dsn)) {
        return NULL;
    }

    Py_INCREF(dsn); /* for ensure_bytes */
    if (!(dsn = psycopg_ensure_bytes(dsn))) { goto exit; }

    options = PQconninfoParse(Bytes_AS_STRING(dsn), &err);
    if (options == NULL) {
        if (err != NULL) {
            PyErr_Format(ProgrammingError, "invalid dsn: %s", err);
            PQfreemem(err);
        } else {
            PyErr_SetString(OperationalError, "PQconninfoParse() failed");
        }
        goto exit;
    }

    res = psycopg_dict_from_conninfo_options(options, /* include_password = */ 1);

exit:
    PQconninfoFree(options);    /* safe on null */
    Py_XDECREF(dsn);

    return res;
}
コード例 #7
0
/* Establishes two network connections to a Postgres server: one for SQL, and one
 * for replication. context->conninfo contains the connection string or URL to connect
 * to, and context->app_name is the client name (which appears, for example, in
 * pg_stat_activity). Returns 0 on success. */
int client_connect(client_context_t context) {
    if (!context->conninfo || context->conninfo[0] == '\0') {
        client_error(context, "conninfo must be set in client context");
        return EINVAL;
    }
    if (!context->app_name || context->app_name[0] == '\0') {
        client_error(context, "app_name must be set in client context");
        return EINVAL;
    }

    context->sql_conn = PQconnectdb(context->conninfo);
    if (PQstatus(context->sql_conn) != CONNECTION_OK) {
        client_error(context, "Connection to database failed: %s", PQerrorMessage(context->sql_conn));
        return EIO;
    }

    /* Parse the connection string into key-value pairs */
    char *error = NULL;
    PQconninfoOption *parsed_opts = PQconninfoParse(context->conninfo, &error);
    if (!parsed_opts) {
        client_error(context, "Replication connection info: %s", error);
        PQfreemem(error);
        return EIO;
    }

    /* Copy the key-value pairs into a new structure with added replication options */
    PQconninfoOption *option;
    int optcount = 2; /* replication, fallback_application_name */
    for (option = parsed_opts; option->keyword != NULL; option++) {
        if (option->val != NULL && option->val[0] != '\0') optcount++;
    }

    const char **keys = malloc((optcount + 1) * sizeof(char *));
    const char **values = malloc((optcount + 1) * sizeof(char *));
    int i = 0;

    for (option = parsed_opts; option->keyword != NULL; option++) {
        if (option->val != NULL && option->val[0] != '\0') {
            keys[i] = option->keyword;
            values[i] = option->val;
            i++;
        }
    }

    keys[i] = "replication";               values[i] = "database";        i++;
    keys[i] = "fallback_application_name"; values[i] = context->app_name; i++;
    keys[i] = NULL;                        values[i] = NULL;

    int err = 0;
    context->repl.conn = PQconnectdbParams(keys, values, true);
    if (PQstatus(context->repl.conn) != CONNECTION_OK) {
        client_error(context, "Replication connection failed: %s", PQerrorMessage(context->repl.conn));
        err = EIO;
    }

    free(keys);
    free(values);
    PQconninfoFree(parsed_opts);
    return err;
}
コード例 #8
0
ファイル: psycopgmodule.c プロジェクト: aisch/psycopg2
static PyObject *
psyco_parse_dsn(PyObject *self, PyObject *args, PyObject *kwargs)
{
    char *err = NULL;
    PQconninfoOption *options = NULL, *o;
    PyObject *dict = NULL, *res = NULL, *dsn;

    static char *kwlist[] = {"dsn", NULL};
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &dsn)) {
        return NULL;
    }

    Py_INCREF(dsn); /* for ensure_bytes */
    if (!(dsn = psycopg_ensure_bytes(dsn))) { goto exit; }

    options = PQconninfoParse(Bytes_AS_STRING(dsn), &err);
    if (options == NULL) {
        if (err != NULL) {
            PyErr_Format(ProgrammingError, "error parsing the dsn: %s", err);
            PQfreemem(err);
        } else {
            PyErr_SetString(OperationalError, "PQconninfoParse() failed");
        }
        goto exit;
    }

    if (!(dict = PyDict_New())) { goto exit; }
    for (o = options; o->keyword != NULL; o++) {
        if (o->val != NULL) {
            PyObject *value;
            if (!(value = Text_FromUTF8(o->val))) { goto exit; }
            if (PyDict_SetItemString(dict, o->keyword, value) != 0) {
                Py_DECREF(value);
                goto exit;
            }
            Py_DECREF(value);
        }
    }

    /* success */
    res = dict;
    dict = NULL;

exit:
    PQconninfoFree(options);    /* safe on null */
    Py_XDECREF(dict);
    Py_XDECREF(dsn);

    return res;
}
コード例 #9
0
ファイル: dbd_pgsql.c プロジェクト: Acidburn0zzz/coturn
static PGconn *get_pqdb_connection(void) {

	persistent_users_db_t *pud = get_persistent_users_db();

	PGconn *pqdbconnection = (PGconn*)pthread_getspecific(connection_key);
	if(pqdbconnection) {
		ConnStatusType status = PQstatus(pqdbconnection);
		if(status != CONNECTION_OK) {
			PQfinish(pqdbconnection);
			pqdbconnection = NULL;
			(void) pthread_setspecific(connection_key, pqdbconnection);
		}
	}
	if(!pqdbconnection) {
		char *errmsg=NULL;
		PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg);
		if(!co) {
			if(errmsg) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg);
				turn_free(errmsg,strlen(errmsg)+1);
			} else {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb);
			}
		} else {
			PQconninfoFree(co);
			if(errmsg)
				turn_free(errmsg,strlen(errmsg)+1);
			pqdbconnection = PQconnectdb(pud->userdb);
			if(!pqdbconnection) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
			} else {
				ConnStatusType status = PQstatus(pqdbconnection);
				if(status != CONNECTION_OK) {
					PQfinish(pqdbconnection);
					pqdbconnection = NULL;
					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
				} else if(!donot_print_connection_success){
					TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb);
					donot_print_connection_success = 1;
				}
			}
		}

		if(pqdbconnection) {
			(void) pthread_setspecific(connection_key, pqdbconnection);
		}
	}
	return pqdbconnection;
}
コード例 #10
0
ファイル: connection_type.c プロジェクト: gencer/psycopg2
RAISES_NEG static int
obscure_password(connectionObject *conn)
{
    PQconninfoOption *options;
    PyObject *d = NULL, *v = NULL, *dsn = NULL;
    char *tmp;
    int rv = -1;

    if (!conn || !conn->dsn) {
        return 0;
    }

    if (!(options = PQconninfoParse(conn->dsn, NULL))) {
        /* unlikely: the dsn was already tested valid */
        return 0;
    }

    if (!(d = psycopg_dict_from_conninfo_options(
            options, /* include_password = */ 1))) {
        goto exit;
    }
    if (NULL == PyDict_GetItemString(d, "password")) {
        /* the dsn doesn't have a password */
        rv = 0;
        goto exit;
    }

    /* scrub the password and put back the connection string together */
    if (!(v = Text_FromUTF8("xxx"))) { goto exit; }
    if (0 > PyDict_SetItemString(d, "password", v)) { goto exit; }
    if (!(dsn = psycopg_make_dsn(Py_None, d))) { goto exit; }
    if (!(dsn = psycopg_ensure_bytes(dsn))) { goto exit; }

    /* Replace the connection string on the connection object */
    tmp = conn->dsn;
    psycopg_strdup(&conn->dsn, Bytes_AS_STRING(dsn), -1);
    PyMem_Free(tmp);

    rv = 0;

exit:
    PQconninfoFree(options);
    Py_XDECREF(v);
    Py_XDECREF(d);
    Py_XDECREF(dsn);

    return rv;
}
コード例 #11
0
ファイル: connection_int.c プロジェクト: psycopg/psycopg2
/* Return 1 if the "replication" keyword is set in the DSN, 0 otherwise */
static int
dsn_has_replication(char *pgdsn)
{
    int ret = 0;
    PQconninfoOption *connopts, *ptr;

    connopts = PQconninfoParse(pgdsn, NULL);

    for(ptr = connopts; ptr->keyword != NULL; ptr++) {
      if(strcmp(ptr->keyword, "replication") == 0 && ptr->val != NULL)
        ret = 1;
    }

    PQconninfoFree(connopts);

    return ret;
}
コード例 #12
0
ファイル: connection.c プロジェクト: Bendalexis/pg_shard
/*
 * ConnectionGetOptionValue inspects the provided connection for an option with
 * a given keyword and returns a new palloc'd string with that options's value.
 * The function returns NULL if the connection has no setting for an option with
 * the provided keyword.
 */
static char *
ConnectionGetOptionValue(PGconn *connection, char *optionKeyword)
{
	char *optionValue = NULL;
	PQconninfoOption *conninfoOptions = PQconninfo(connection);

	for (PQconninfoOption *option = conninfoOptions; option->keyword != NULL; option++)
	{
		if (strncmp(option->keyword, optionKeyword, NAMEDATALEN) == 0)
		{
			optionValue = pstrdup(option->val);
		}
	}

	PQconninfoFree(conninfoOptions);

	return optionValue;
}
コード例 #13
0
CAMLprim value PQconndefaults_stub(value __unused v_unit)
{
  CAMLparam0();
  CAMLlocal2(v_res, v_el);
  PQconninfoOption *cios = PQconndefaults(), *p = cios;
  int i, j, n;

  while (p->keyword != NULL) p++;

  n = p - cios;
  p = cios;
  v_res = caml_alloc_tuple(n);

  for (i = 0; i < n; i++, p++) {
    value v_field;
    v_el = caml_alloc_small(7, 0);
    for (j = 0; j < 7; j++) Field(v_el, j) = v_None;
    Store_field(v_res, i, v_el);
    v_field = caml_copy_string(p->keyword);
    Field(v_el, 0) = v_field;
    if (p->envvar) {
      v_field = make_some(caml_copy_string(p->envvar));
      caml_modify(&Field(v_el, 1), v_field);
    }
    if (p->compiled) {
      v_field = make_some(caml_copy_string(p->compiled));
      caml_modify(&Field(v_el, 2), v_field);
    };
    if (p->val) {
      v_field = make_some(caml_copy_string(p->val));
      caml_modify(&Field(v_el, 3), v_field);
    };
    v_field = caml_copy_string(p->label);
    caml_modify(&Field(v_el, 4), v_field);
    v_field = caml_copy_string(p->dispchar);
    caml_modify(&Field(v_el, 5), v_field);
    caml_modify(&Field(v_el, 6), Val_int(p->dispsize));
  };

  PQconninfoFree(cios);

  CAMLreturn(v_res);
}
コード例 #14
0
ファイル: config.c プロジェクト: Bazoozoo/repmgr
/*
 * Parse configuration file; if any errors are encountered,
 * list them and exit.
 *
 * Ensure any default values set here are synced with repmgr.conf.sample
 * and any other documentation.
 */
bool
parse_config(t_configuration_options *options)
{
	FILE	   *fp;
	char	   *s,
				buff[MAXLINELENGTH];
	char		name[MAXLEN];
	char		value[MAXLEN];

	/* For sanity-checking provided conninfo string */
	PQconninfoOption *conninfo_options;
	char       *conninfo_errmsg = NULL;

	/* Collate configuration file errors here for friendlier reporting */
	static ErrorList config_errors = { NULL, NULL };

	fp = fopen(config_file_path, "r");

	/*
	 * Since some commands don't require a config file at all, not having one
	 * isn't necessarily a problem.
	 *
	 * If the user explictly provided a configuration file and we can't
	 * read it we'll raise an error.
	 *
	 * If no configuration file was provided, we'll try and read the default\
	 * file if it exists and is readable, but won't worry if it's not.
	 */
	if (fp == NULL)
	{
		if (config_file_provided)
		{
			log_err(_("unable to open provided configuration file '%s'; terminating\n"), config_file_path);
			exit(ERR_BAD_CONFIG);
		}

		log_notice(_("no configuration file provided and default file '%s' not found - "
					 "continuing with default values\n"),
				   DEFAULT_CONFIG_FILE);
		return false;
	}

	/* Initialize configuration options with sensible defaults
	 * note: the default log level is set in log.c and does not need
	 * to be initialised here
	 */
	memset(options->cluster_name, 0, sizeof(options->cluster_name));
	options->node = -1;
	options->upstream_node = NO_UPSTREAM_NODE;
	options->use_replication_slots = 0;
	memset(options->conninfo, 0, sizeof(options->conninfo));
	options->failover = MANUAL_FAILOVER;
	options->priority = DEFAULT_PRIORITY;
	memset(options->node_name, 0, sizeof(options->node_name));
	memset(options->promote_command, 0, sizeof(options->promote_command));
	memset(options->follow_command, 0, sizeof(options->follow_command));
	memset(options->rsync_options, 0, sizeof(options->rsync_options));
	memset(options->ssh_options, 0, sizeof(options->ssh_options));
	memset(options->pg_bindir, 0, sizeof(options->pg_bindir));
	memset(options->pg_ctl_options, 0, sizeof(options->pg_ctl_options));
	memset(options->pg_basebackup_options, 0, sizeof(options->pg_basebackup_options));

	/* default master_response_timeout is 60 seconds */
	options->master_response_timeout = 60;

	/* default to 6 reconnection attempts at intervals of 10 seconds */
	options->reconnect_attempts = 6;
	options->reconnect_interval = 10;

	options->monitor_interval_secs = 2;
	options->retry_promote_interval_secs = 300;

	memset(options->event_notification_command, 0, sizeof(options->event_notification_command));

	options->tablespace_mapping.head = NULL;
	options->tablespace_mapping.tail = NULL;


	/* Read next line */
	while ((s = fgets(buff, sizeof buff, fp)) != NULL)
	{
		bool known_parameter = true;

		/* Parse name/value pair from line */
		parse_line(buff, name, value);

		/* Skip blank lines */
		if (!strlen(name))
			continue;

		/* Skip comments */
		if (name[0] == '#')
			continue;

		/* Copy into correct entry in parameters struct */
		if (strcmp(name, "cluster") == 0)
			strncpy(options->cluster_name, value, MAXLEN);
		else if (strcmp(name, "node") == 0)
			options->node = repmgr_atoi(value, "node", &config_errors);
		else if (strcmp(name, "upstream_node") == 0)
			options->upstream_node = repmgr_atoi(value, "upstream_node", &config_errors);
		else if (strcmp(name, "conninfo") == 0)
			strncpy(options->conninfo, value, MAXLEN);
		else if (strcmp(name, "rsync_options") == 0)
			strncpy(options->rsync_options, value, QUERY_STR_LEN);
		else if (strcmp(name, "ssh_options") == 0)
			strncpy(options->ssh_options, value, QUERY_STR_LEN);
		else if (strcmp(name, "loglevel") == 0)
			strncpy(options->loglevel, value, MAXLEN);
		else if (strcmp(name, "logfacility") == 0)
			strncpy(options->logfacility, value, MAXLEN);
		else if (strcmp(name, "failover") == 0)
		{
			char		failoverstr[MAXLEN];

			strncpy(failoverstr, value, MAXLEN);

			if (strcmp(failoverstr, "manual") == 0)
			{
				options->failover = MANUAL_FAILOVER;
			}
			else if (strcmp(failoverstr, "automatic") == 0)
			{
				options->failover = AUTOMATIC_FAILOVER;
			}
			else
			{
				log_err(_("value for 'failover' must be 'automatic' or 'manual'\n"));
				exit(ERR_BAD_CONFIG);
			}
		}
		else if (strcmp(name, "priority") == 0)
			options->priority = repmgr_atoi(value, "priority", &config_errors);
		else if (strcmp(name, "node_name") == 0)
			strncpy(options->node_name, value, MAXLEN);
		else if (strcmp(name, "promote_command") == 0)
			strncpy(options->promote_command, value, MAXLEN);
		else if (strcmp(name, "follow_command") == 0)
			strncpy(options->follow_command, value, MAXLEN);
		else if (strcmp(name, "master_response_timeout") == 0)
			options->master_response_timeout = repmgr_atoi(value, "master_response_timeout", &config_errors);
		/* 'primary_response_timeout' as synonym for 'master_response_timeout' -
		 * we'll switch terminology in a future release (3.1?)
		 */
		else if (strcmp(name, "primary_response_timeout") == 0)
			options->master_response_timeout = repmgr_atoi(value, "primary_response_timeout", &config_errors);
		else if (strcmp(name, "reconnect_attempts") == 0)
			options->reconnect_attempts = repmgr_atoi(value, "reconnect_attempts", &config_errors);
		else if (strcmp(name, "reconnect_interval") == 0)
			options->reconnect_interval = repmgr_atoi(value, "reconnect_interval", &config_errors);
		else if (strcmp(name, "pg_bindir") == 0)
			strncpy(options->pg_bindir, value, MAXLEN);
		else if (strcmp(name, "pg_ctl_options") == 0)
			strncpy(options->pg_ctl_options, value, MAXLEN);
		else if (strcmp(name, "pg_basebackup_options") == 0)
			strncpy(options->pg_basebackup_options, value, MAXLEN);
		else if (strcmp(name, "logfile") == 0)
			strncpy(options->logfile, value, MAXLEN);
		else if (strcmp(name, "monitor_interval_secs") == 0)
			options->monitor_interval_secs = repmgr_atoi(value, "monitor_interval_secs", &config_errors);
		else if (strcmp(name, "retry_promote_interval_secs") == 0)
			options->retry_promote_interval_secs = repmgr_atoi(value, "retry_promote_interval_secs", &config_errors);
		else if (strcmp(name, "use_replication_slots") == 0)
			/* XXX we should have a dedicated boolean argument format */
			options->use_replication_slots = repmgr_atoi(value, "use_replication_slots", &config_errors);
		else if (strcmp(name, "event_notification_command") == 0)
			strncpy(options->event_notification_command, value, MAXLEN);
		else if (strcmp(name, "event_notifications") == 0)
			parse_event_notifications_list(options, value);
		else if (strcmp(name, "tablespace_mapping") == 0)
			tablespace_list_append(options, value);
		else
		{
			known_parameter = false;
			log_warning(_("%s/%s: unknown name/value pair provided; ignoring\n"), name, value);
		}

		/*
		 * Raise an error if a known parameter is provided with an empty value.
		 * Currently there's no reason why empty parameters are needed; if
		 * we want to accept those, we'd need to add stricter default checking,
		 * as currently e.g. an empty `node` value will be converted to '0'.
		 */
		if (known_parameter == true && !strlen(value)) {
			char	   error_message_buf[MAXLEN] = "";
			snprintf(error_message_buf,
					 MAXLEN,
					 _("no value provided for parameter \"%s\""),
					 name);

			error_list_append(&config_errors, error_message_buf);
		}
	}

	fclose(fp);

	/* Check config settings */

	/* The following checks are for the presence of the parameter */
	if (*options->cluster_name == '\0')
	{
		error_list_append(&config_errors, _("\"cluster\": parameter was not found\n"));
	}

	if (options->node == -1)
	{
		error_list_append(&config_errors, _("\"node\": parameter was not found\n"));
	}

	if (*options->node_name == '\0')
	{
		error_list_append(&config_errors, _("\"node_name\": parameter was not found\n"));
	}

	if (*options->conninfo == '\0')
	{
		error_list_append(&config_errors, _("\"conninfo\": parameter was not found\n"));
	}
	else
	{

		/* Sanity check the provided conninfo string
		 *
		 * NOTE: this verifies the string format and checks for valid options
		 * but does not sanity check values
		 */
		conninfo_options = PQconninfoParse(options->conninfo, &conninfo_errmsg);
		if (conninfo_options == NULL)
		{
			char	   error_message_buf[MAXLEN] = "";
			snprintf(error_message_buf,
					 MAXLEN,
					 _("\"conninfo\": %s"),
					 conninfo_errmsg);

			error_list_append(&config_errors, error_message_buf);
		}

		PQconninfoFree(conninfo_options);
	}

	// exit_with_errors here
	if (config_errors.head != NULL)
	{
		exit_with_errors(&config_errors);
	}
	return true;
}
コード例 #15
0
ファイル: streamutil.c プロジェクト: aakashgoel/postgres
/*
 * Connect to the server. Returns a valid PGconn pointer if connected,
 * or NULL on non-permanent error. On permanent error, the function will
 * call exit(1) directly.
 */
PGconn *
GetConnection(void)
{
	PGconn	   *tmpconn;
	int			argcount = 7;	/* dbname, replication, fallback_app_name,
								 * host, user, port, password */
	int			i;
	const char **keywords;
	const char **values;
	const char *tmpparam;
	bool		need_password;
	PQconninfoOption *conn_opts = NULL;
	PQconninfoOption *conn_opt;
	char	   *err_msg = NULL;

	/*
	 * Merge the connection info inputs given in form of connection string,
	 * options and default values (dbname=replication, replication=true, etc.)
	 */
	i = 0;
	if (connection_string)
	{
		conn_opts = PQconninfoParse(connection_string, &err_msg);
		if (conn_opts == NULL)
		{
			fprintf(stderr, "%s: %s", progname, err_msg);
			exit(1);
		}

		for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
		{
			if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
				argcount++;
		}

		keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
		values = pg_malloc0((argcount + 1) * sizeof(*values));

		for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
		{
			if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
			{
				keywords[i] = conn_opt->keyword;
				values[i] = conn_opt->val;
				i++;
			}
		}
	}
	else
	{
		keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
		values = pg_malloc0((argcount + 1) * sizeof(*values));
	}

	keywords[i] = "dbname";
	values[i] = "replication";
	i++;
	keywords[i] = "replication";
	values[i] = "true";
	i++;
	keywords[i] = "fallback_application_name";
	values[i] = progname;
	i++;

	if (dbhost)
	{
		keywords[i] = "host";
		values[i] = dbhost;
		i++;
	}
	if (dbuser)
	{
		keywords[i] = "user";
		values[i] = dbuser;
		i++;
	}
	if (dbport)
	{
		keywords[i] = "port";
		values[i] = dbport;
		i++;
	}

	/* If -W was given, force prompt for password, but only the first time */
	need_password = (dbgetpassword == 1 && dbpassword == NULL);

	while (true)
	{
		/* Get a new password if appropriate */
		if (need_password)
		{
			if (dbpassword)
				free(dbpassword);
			dbpassword = simple_prompt(_("Password: "******"password";
			values[i] = dbpassword;
		}
		else
		{
			keywords[i] = NULL;
			values[i] = NULL;
		}

		tmpconn = PQconnectdbParams(keywords, values, true);

		/*
		 * If there is too little memory even to allocate the PGconn object
		 * and PQconnectdbParams returns NULL, we call exit(1) directly.
		 */
		if (!tmpconn)
		{
			fprintf(stderr, _("%s: could not connect to server\n"),
					progname);
			exit(1);
		}

		/* If we need a password and -w wasn't given, loop back and get one */
		if (PQstatus(tmpconn) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(tmpconn) &&
			dbgetpassword != -1)
		{
			PQfinish(tmpconn);
			need_password = true;
		}
		else
			break;
	}

	if (PQstatus(tmpconn) != CONNECTION_OK)
	{
		fprintf(stderr, _("%s: could not connect to server: %s\n"),
				progname, PQerrorMessage(tmpconn));
		PQfinish(tmpconn);
		free(values);
		free(keywords);
		if (conn_opts)
			PQconninfoFree(conn_opts);
		return NULL;
	}

	/* Connection ok! */
	free(values);
	free(keywords);
	if (conn_opts)
		PQconninfoFree(conn_opts);

	/*
	 * Ensure we have the same value of integer timestamps as the server we
	 * are connecting to.
	 */
	tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
	if (!tmpparam)
	{
		fprintf(stderr,
		 _("%s: could not determine server setting for integer_datetimes\n"),
				progname);
		PQfinish(tmpconn);
		exit(1);
	}

#ifdef HAVE_INT64_TIMESTAMP
	if (strcmp(tmpparam, "on") != 0)
#else
	if (strcmp(tmpparam, "off") != 0)
#endif
	{
		fprintf(stderr,
			 _("%s: integer_datetimes compile flag does not match server\n"),
				progname);
		PQfinish(tmpconn);
		exit(1);
	}

	return tmpconn;
}
コード例 #16
0
ファイル: pg_basebackup.c プロジェクト: 42penguins/postgres
/*
 * Create a recovery.conf file in memory using a PQExpBuffer
 */
static void
GenerateRecoveryConf(PGconn *conn)
{
	PQconninfoOption *connOptions;
	PQconninfoOption *option;
	PQExpBufferData conninfo_buf;
	char	   *escaped;

	recoveryconfcontents = createPQExpBuffer();
	if (!recoveryconfcontents)
	{
		fprintf(stderr, _("%s: out of memory\n"), progname);
		disconnect_and_exit(1);
	}

	connOptions = PQconninfo(conn);
	if (connOptions == NULL)
	{
		fprintf(stderr, _("%s: out of memory\n"), progname);
		disconnect_and_exit(1);
	}

	appendPQExpBufferStr(recoveryconfcontents, "standby_mode = 'on'\n");

	initPQExpBuffer(&conninfo_buf);
	for (option = connOptions; option && option->keyword; option++)
	{
		/*
		 * Do not emit this setting if: - the setting is "replication",
		 * "dbname" or "fallback_application_name", since these would be
		 * overridden by the libpqwalreceiver module anyway. - not set or
		 * empty.
		 */
		if (strcmp(option->keyword, "replication") == 0 ||
			strcmp(option->keyword, "dbname") == 0 ||
			strcmp(option->keyword, "fallback_application_name") == 0 ||
			(option->val == NULL) ||
			(option->val != NULL && option->val[0] == '\0'))
			continue;

		/* Separate key-value pairs with spaces */
		if (conninfo_buf.len != 0)
			appendPQExpBufferStr(&conninfo_buf, " ");

		/*
		 * Write "keyword=value" pieces, the value string is escaped and/or
		 * quoted if necessary.
		 */
		escaped = escapeConnectionParameter(option->val);
		appendPQExpBuffer(&conninfo_buf, "%s=%s", option->keyword, escaped);
		free(escaped);
	}

	/*
	 * Escape the connection string, so that it can be put in the config file.
	 * Note that this is different from the escaping of individual connection
	 * options above!
	 */
	escaped = escape_quotes(conninfo_buf.data);
	appendPQExpBuffer(recoveryconfcontents, "primary_conninfo = '%s'\n", escaped);
	free(escaped);

	if (PQExpBufferBroken(recoveryconfcontents) ||
		PQExpBufferDataBroken(conninfo_buf))
	{
		fprintf(stderr, _("%s: out of memory\n"), progname);
		disconnect_and_exit(1);
	}

	termPQExpBuffer(&conninfo_buf);

	PQconninfoFree(connOptions);
}
コード例 #17
0
/*
 * Parse configuration file; if any errors are encountered,
 * list them and exit.
 *
 * Ensure any default values set here are synced with repmgr.conf.sample
 * and any other documentation.
 */
void
_parse_config(t_configuration_options *options, ItemList *error_list)
{
	FILE	   *fp;
	char	   *s,
				buf[MAXLINELENGTH];
	char		name[MAXLEN];
	char		value[MAXLEN];

	/* For sanity-checking provided conninfo string */
	PQconninfoOption *conninfo_options;
	char	   *conninfo_errmsg = NULL;

	bool		node_found = false;

	/* Initialize configuration options with sensible defaults
	 * note: the default log level is set in log.c and does not need
	 * to be initialised here
	 */
	memset(options->cluster_name, 0, sizeof(options->cluster_name));
	options->node = UNKNOWN_NODE_ID;
	options->upstream_node = NO_UPSTREAM_NODE;
	options->use_replication_slots = 0;
	memset(options->conninfo, 0, sizeof(options->conninfo));
	memset(options->barman_server, 0, sizeof(options->barman_server));
	memset(options->barman_config, 0, sizeof(options->barman_config));
	options->failover = MANUAL_FAILOVER;
	options->priority = DEFAULT_PRIORITY;
	memset(options->node_name, 0, sizeof(options->node_name));
	memset(options->promote_command, 0, sizeof(options->promote_command));
	memset(options->follow_command, 0, sizeof(options->follow_command));
	memset(options->service_stop_command, 0, sizeof(options->service_stop_command));
	memset(options->service_start_command, 0, sizeof(options->service_start_command));
	memset(options->service_restart_command, 0, sizeof(options->service_restart_command));
	memset(options->service_reload_command, 0, sizeof(options->service_reload_command));
	memset(options->service_promote_command, 0, sizeof(options->service_promote_command));
	memset(options->rsync_options, 0, sizeof(options->rsync_options));
	memset(options->ssh_options, 0, sizeof(options->ssh_options));
	memset(options->pg_bindir, 0, sizeof(options->pg_bindir));
	memset(options->pg_ctl_options, 0, sizeof(options->pg_ctl_options));
	memset(options->pg_basebackup_options, 0, sizeof(options->pg_basebackup_options));
	memset(options->restore_command, 0, sizeof(options->restore_command));

	/* default master_response_timeout is 60 seconds */
	options->master_response_timeout = 60;

	/* default to 6 reconnection attempts at intervals of 10 seconds */
	options->reconnect_attempts = 6;
	options->reconnect_interval = 10;

	options->monitor_interval_secs = 2;
	options->retry_promote_interval_secs = 300;

	/* default to resyncing repl_nodes table every 30 seconds on the witness server */
	options->witness_repl_nodes_sync_interval_secs = 30;

	memset(options->event_notification_command, 0, sizeof(options->event_notification_command));
	options->event_notifications.head = NULL;
	options->event_notifications.tail = NULL;

	options->tablespace_mapping.head = NULL;
	options->tablespace_mapping.tail = NULL;

	/*
	 * If no configuration file available (user didn't specify and none found
	 * in the default locations), return with default values
	 */
	if (config_file_found == false)
	{
		log_verbose(LOG_NOTICE, _("no configuration file provided and no default file found - "
					 "continuing with default values\n"));
		return;
	}

	fp = fopen(config_file_path, "r");

	/*
	 * A configuration file has been found, either provided by the user
	 * or found in one of the default locations. If we can't open it,
	 * fail with an error.
	 */
	if (fp == NULL)
	{
		if (config_file_provided)
		{
			log_err(_("unable to open provided configuration file \"%s\"; terminating\n"), config_file_path);
		}
		else
		{
			log_err(_("unable to open default configuration file  \"%s\"; terminating\n"), config_file_path);
		}

		exit(ERR_BAD_CONFIG);
	}

	/* Read file */
	while ((s = fgets(buf, sizeof buf, fp)) != NULL)
	{
		bool known_parameter = true;

		/* Parse name/value pair from line */
		parse_line(buf, name, value);

		/* Skip blank lines */
		if (!strlen(name))
			continue;

		/* Skip comments */
		if (name[0] == '#')
			continue;

		/* Copy into correct entry in parameters struct */
		if (strcmp(name, "cluster") == 0)
			strncpy(options->cluster_name, value, MAXLEN);
		else if (strcmp(name, "node") == 0)
		{
			options->node = repmgr_atoi(value, "node", error_list, false);
			node_found = true;
		}
		else if (strcmp(name, "upstream_node") == 0)
			options->upstream_node = repmgr_atoi(value, "upstream_node", error_list, false);
		else if (strcmp(name, "conninfo") == 0)
			strncpy(options->conninfo, value, MAXLEN);
		else if (strcmp(name, "barman_server") == 0)
			strncpy(options->barman_server, value, MAXLEN);
		else if (strcmp(name, "barman_config") == 0)
			strncpy(options->barman_config, value, MAXLEN);
		else if (strcmp(name, "rsync_options") == 0)
			strncpy(options->rsync_options, value, QUERY_STR_LEN);
		else if (strcmp(name, "ssh_options") == 0)
			strncpy(options->ssh_options, value, QUERY_STR_LEN);
		else if (strcmp(name, "loglevel") == 0)
			strncpy(options->loglevel, value, MAXLEN);
		else if (strcmp(name, "logfacility") == 0)
			strncpy(options->logfacility, value, MAXLEN);
		else if (strcmp(name, "failover") == 0)
		{
			char		failoverstr[MAXLEN];

			strncpy(failoverstr, value, MAXLEN);

			if (strcmp(failoverstr, "manual") == 0)
			{
				options->failover = MANUAL_FAILOVER;
			}
			else if (strcmp(failoverstr, "automatic") == 0)
			{
				options->failover = AUTOMATIC_FAILOVER;
			}
			else
			{
				item_list_append(error_list, _("value for 'failover' must be 'automatic' or 'manual'\n"));
			}
		}
		else if (strcmp(name, "priority") == 0)
			options->priority = repmgr_atoi(value, "priority", error_list, true);
		else if (strcmp(name, "node_name") == 0)
			strncpy(options->node_name, value, MAXLEN);
		else if (strcmp(name, "promote_command") == 0)
			strncpy(options->promote_command, value, MAXLEN);
		else if (strcmp(name, "follow_command") == 0)
			strncpy(options->follow_command, value, MAXLEN);
		else if (strcmp(name, "service_stop_command") == 0)
			strncpy(options->service_stop_command, value, MAXLEN);
		else if (strcmp(name, "service_start_command") == 0)
			strncpy(options->service_start_command, value, MAXLEN);
		else if (strcmp(name, "service_restart_command") == 0)
			strncpy(options->service_restart_command, value, MAXLEN);
		else if (strcmp(name, "service_reload_command") == 0)
			strncpy(options->service_reload_command, value, MAXLEN);
		else if (strcmp(name, "service_promote_command") == 0)
			strncpy(options->service_promote_command, value, MAXLEN);
		else if (strcmp(name, "master_response_timeout") == 0)
			options->master_response_timeout = repmgr_atoi(value, "master_response_timeout", error_list, false);
		/*
		 * 'primary_response_timeout' as synonym for 'master_response_timeout' -
		 * we'll switch terminology in a future release (3.1?)
		 */
		else if (strcmp(name, "primary_response_timeout") == 0)
			options->master_response_timeout = repmgr_atoi(value, "primary_response_timeout", error_list, false);
		else if (strcmp(name, "reconnect_attempts") == 0)
			options->reconnect_attempts = repmgr_atoi(value, "reconnect_attempts", error_list, false);
		else if (strcmp(name, "reconnect_interval") == 0)
			options->reconnect_interval = repmgr_atoi(value, "reconnect_interval", error_list, false);
		else if (strcmp(name, "pg_bindir") == 0)
			strncpy(options->pg_bindir, value, MAXLEN);
		else if (strcmp(name, "pg_ctl_options") == 0)
			strncpy(options->pg_ctl_options, value, MAXLEN);
		else if (strcmp(name, "pg_basebackup_options") == 0)
			strncpy(options->pg_basebackup_options, value, MAXLEN);
		else if (strcmp(name, "logfile") == 0)
			strncpy(options->logfile, value, MAXLEN);
		else if (strcmp(name, "monitor_interval_secs") == 0)
			options->monitor_interval_secs = repmgr_atoi(value, "monitor_interval_secs", error_list, false);
		else if (strcmp(name, "retry_promote_interval_secs") == 0)
			options->retry_promote_interval_secs = repmgr_atoi(value, "retry_promote_interval_secs", error_list, false);
		else if (strcmp(name, "witness_repl_nodes_sync_interval_secs") == 0)
			options->witness_repl_nodes_sync_interval_secs = repmgr_atoi(value, "witness_repl_nodes_sync_interval_secs", error_list, false);
		else if (strcmp(name, "use_replication_slots") == 0)
			/* XXX we should have a dedicated boolean argument format */
			options->use_replication_slots = repmgr_atoi(value, "use_replication_slots", error_list, false);
		else if (strcmp(name, "event_notification_command") == 0)
			strncpy(options->event_notification_command, value, MAXLEN);
		else if (strcmp(name, "event_notifications") == 0)
			parse_event_notifications_list(options, value);
		else if (strcmp(name, "tablespace_mapping") == 0)
			tablespace_list_append(options, value);
		else if (strcmp(name, "restore_command") == 0)
			strncpy(options->restore_command, value, MAXLEN);
		else
		{
			known_parameter = false;
			log_warning(_("%s/%s: unknown name/value pair provided; ignoring\n"), name, value);
		}

		/*
		 * Raise an error if a known parameter is provided with an empty value.
		 * Currently there's no reason why empty parameters are needed; if
		 * we want to accept those, we'd need to add stricter default checking,
		 * as currently e.g. an empty `node` value will be converted to '0'.
		 */
		if (known_parameter == true && !strlen(value)) {
			char	   error_message_buf[MAXLEN] = "";
			snprintf(error_message_buf,
					 MAXLEN,
					 _("no value provided for parameter \"%s\""),
					 name);

			item_list_append(error_list, error_message_buf);
		}
	}

	fclose(fp);


	if (node_found == false)
	{
		item_list_append(error_list, _("\"node\": parameter was not found"));
	}
	else if (options->node == 0)
	{
		item_list_append(error_list, _("\"node\": must be greater than zero"));
	}

	if (strlen(options->conninfo))
	{

		/* Sanity check the provided conninfo string
		 *
		 * NOTE: PQconninfoParse() verifies the string format and checks for valid options
		 * but does not sanity check values
		 */
		conninfo_options = PQconninfoParse(options->conninfo, &conninfo_errmsg);
		if (conninfo_options == NULL)
		{
			char	   error_message_buf[MAXLEN] = "";
			snprintf(error_message_buf,
					 MAXLEN,
					 _("\"conninfo\": %s"),
					 conninfo_errmsg);

			item_list_append(error_list, error_message_buf);
		}

		PQconninfoFree(conninfo_options);
	}
}