From: Tom Lane Date: Mon, 4 Mar 2002 01:46:04 +0000 (+0000) Subject: Further work on elog cleanup: fix some bogosities in elog's logic about X-Git-Tag: REL7_3~1995 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=36f693ec69bd412817021ae530c729b414822ebc;p=postgresql Further work on elog cleanup: fix some bogosities in elog's logic about when to send what to which, prevent recursion by introducing new COMMERROR elog level for client-communication problems, get rid of direct writes to stderr in backend/libpq files, prevent non-error elogs from going to client during the authentication cycle. --- diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile index f45feaed1f..f5c2339f1c 100644 --- a/src/backend/libpq/Makefile +++ b/src/backend/libpq/Makefile @@ -4,7 +4,7 @@ # Makefile for libpq subsystem (backend half of libpq interface) # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.28 2001/11/13 22:06:58 momjian Exp $ +# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.29 2002/03/04 01:46:02 tgl Exp $ # #------------------------------------------------------------------------- @@ -16,7 +16,7 @@ include $(top_builddir)/src/Makefile.global OBJS = be-fsstubs.o \ auth.o crypt.o hba.o md5.o password.o \ - pqcomm.o pqformat.o pqsignal.o util.o + pqcomm.o pqformat.o pqsignal.o all: SUBSYS.o diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 72e4ef4366..f20a02788e 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.76 2002/03/02 21:39:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.77 2002/03/04 01:46:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -105,45 +105,34 @@ pg_krb4_recvauth(Port *port) version); if (status != KSUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb4_recvauth: kerberos error: %s\n", - krb_err_txt[status]); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pg_krb4_recvauth: kerberos error: %s", + krb_err_txt[status]); return STATUS_ERROR; } - if (strncmp(version, PG_KRB4_VERSION, KRB_SENDAUTH_VLEN)) + if (strncmp(version, PG_KRB4_VERSION, KRB_SENDAUTH_VLEN) != 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb4_recvauth: protocol version != \"%s\"\n", - PG_KRB4_VERSION); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pg_krb4_recvauth: protocol version \"%s\" != \"%s\"", + version, PG_KRB4_VERSION); return STATUS_ERROR; } - if (strncmp(port->user, auth_data.pname, SM_USER)) + if (strncmp(port->user, auth_data.pname, SM_USER) != 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb4_recvauth: name \"%s\" != \"%s\"\n", - port->user, auth_data.pname); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pg_krb4_recvauth: name \"%s\" != \"%s\"", + port->user, auth_data.pname); return STATUS_ERROR; } return STATUS_OK; } #else + static int pg_krb4_recvauth(Port *port) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb4_recvauth: Kerberos not implemented on this server.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - + elog(LOG, "pg_krb4_recvauth: Kerberos not implemented on this server"); return STATUS_ERROR; } + #endif /* KRB4 */ @@ -201,9 +190,8 @@ pg_krb5_init(void) retval = krb5_init_context(&pg_krb5_context); if (retval) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_init: krb5_init_context returned" - " Kerberos error %d\n", retval); + elog(LOG, "pg_krb5_init: krb5_init_context returned Kerberos error %d", + retval); com_err("postgres", retval, "while initializing krb5"); return STATUS_ERROR; } @@ -211,9 +199,8 @@ pg_krb5_init(void) retval = krb5_kt_resolve(pg_krb5_context, pg_krb_server_keyfile, &pg_krb5_keytab); if (retval) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_init: krb5_kt_resolve returned" - " Kerberos error %d\n", retval); + elog(LOG, "pg_krb5_init: krb5_kt_resolve returned Kerberos error %d", + retval); com_err("postgres", retval, "while resolving keytab file %s", pg_krb_server_keyfile); krb5_free_context(pg_krb5_context); @@ -224,9 +211,8 @@ pg_krb5_init(void) KRB5_NT_SRV_HST, &pg_krb5_server); if (retval) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_init: krb5_sname_to_principal returned" - " Kerberos error %d\n", retval); + elog(LOG, "pg_krb5_init: krb5_sname_to_principal returned Kerberos error %d", + retval); com_err("postgres", retval, "while getting server principal for service %s", PG_KRB_SRVNAM); @@ -269,9 +255,8 @@ pg_krb5_recvauth(Port *port) pg_krb5_server, 0, pg_krb5_keytab, &ticket); if (retval) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_recvauth: krb5_recvauth returned" - " Kerberos error %d\n", retval); + elog(LOG, "pg_krb5_recvauth: krb5_recvauth returned Kerberos error %d", + retval); com_err("postgres", retval, "from krb5_recvauth"); return STATUS_ERROR; } @@ -294,9 +279,8 @@ pg_krb5_recvauth(Port *port) #endif if (retval) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_recvauth: krb5_unparse_name returned" - " Kerberos error %d\n", retval); + elog(LOG, "pg_krb5_recvauth: krb5_unparse_name returned Kerberos error %d", + retval); com_err("postgres", retval, "while unparsing client name"); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); @@ -306,9 +290,8 @@ pg_krb5_recvauth(Port *port) kusername = pg_an_to_ln(kusername); if (strncmp(port->user, kusername, SM_USER)) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"\n", - port->user, kusername); + elog(LOG, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"", + port->user, kusername); ret = STATUS_ERROR; } else @@ -322,16 +305,14 @@ pg_krb5_recvauth(Port *port) } #else + static int pg_krb5_recvauth(Port *port) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_krb5_recvauth: Kerberos not implemented on this server.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - + elog(LOG, "pg_krb5_recvauth: Kerberos not implemented on this server"); return STATUS_ERROR; } + #endif /* KRB5 */ @@ -388,10 +369,7 @@ recv_and_check_passwordv0(Port *port) if (user == NULL || password == NULL) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pg_password_recvauth: badly formed password packet.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pg_password_recvauth: badly formed password packet"); status = STATUS_ERROR; } else @@ -530,7 +508,7 @@ ClientAuthentication(Port *port) if (port->raddr.sa.sa_family == AF_INET) hostinfo = inet_ntoa(port->raddr.in.sin_addr); elog(FATAL, - "No pg_hba.conf entry for host %s, user %s, database %s", + "No pg_hba.conf entry for host %s, user %s, database %s", hostinfo, port->user, port->database); break; } @@ -563,8 +541,7 @@ ClientAuthentication(Port *port) int on = 1; if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) - elog(FATAL, - "pg_local_sendauth: can't do setsockopt: %s\n", strerror(errno)); + elog(FATAL, "pg_local_sendauth: can't do setsockopt: %m"); } #endif if (port->raddr.sa.sa_family == AF_UNIX) @@ -653,17 +630,12 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_re switch (msg[0]->msg_style) { case PAM_ERROR_MSG: - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pam_passwd_conv_proc: Error from underlying PAM layer: '%s'\n", msg[0]->msg); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pam_passwd_conv_proc: Error from underlying PAM layer: '%s'", + msg[0]->msg); return PAM_CONV_ERR; default: - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "pam_passwd_conv_proc: Unexpected PAM conversation %d/'%s'\n", - msg[0]->msg_style, msg[0]->msg); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pam_passwd_conv_proc: Unexpected PAM conversation %d/'%s'", + msg[0]->msg_style, msg[0]->msg); return PAM_CONV_ERR; } } @@ -691,12 +663,11 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_re initStringInfo(&buf); pq_getstr(&buf); - elog(DEBUG5, "received PAM packet with len=%d, pw=%s\n", len, buf.data); + elog(DEBUG5, "received PAM packet with len=%d, pw=%s", len, buf.data); if (strlen(buf.data) == 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pam_passwd_conv_proc: no password\n"); - fputs(PQerrormsg, stderr); + elog(LOG, "pam_passwd_conv_proc: no password"); return PAM_CONV_ERR; } appdata_ptr = buf.data; @@ -709,9 +680,7 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_re *resp = calloc(num_msg, sizeof(struct pam_response)); if (!*resp) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, "pam_passwd_conv_proc: Out of memory!\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "pam_passwd_conv_proc: Out of memory!"); if (buf.data) pfree(buf.data); return PAM_CONV_ERR; @@ -755,11 +724,8 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "CheckPAMAuth: Failed to create PAM authenticator: '%s'\n", - pam_strerror(pamh, retval)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "CheckPAMAuth: Failed to create PAM authenticator: '%s'", + pam_strerror(pamh, retval)); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -768,11 +734,8 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "CheckPAMAuth: pam_set_item(PAM_USER) failed: '%s'\n", - pam_strerror(pamh, retval)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "CheckPAMAuth: pam_set_item(PAM_USER) failed: '%s'", + pam_strerror(pamh, retval)); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -781,11 +744,8 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "CheckPAMAuth: pam_set_item(PAM_CONV) failed: '%s'\n", - pam_strerror(pamh, retval)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "CheckPAMAuth: pam_set_item(PAM_CONV) failed: '%s'", + pam_strerror(pamh, retval)); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -794,11 +754,8 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "CheckPAMAuth: pam_authenticate failed: '%s'\n", - pam_strerror(pamh, retval)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "CheckPAMAuth: pam_authenticate failed: '%s'", + pam_strerror(pamh, retval)); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -807,11 +764,8 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "CheckPAMAuth: pam_acct_mgmt failed: '%s'\n", - pam_strerror(pamh, retval)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "CheckPAMAuth: pam_acct_mgmt failed: '%s'", + pam_strerror(pamh, retval)); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -820,11 +774,8 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "CheckPAMAuth: Failed to release PAM authenticator: '%s'\n", - pam_strerror(pamh, retval)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "CheckPAMAuth: Failed to release PAM authenticator: '%s'", + pam_strerror(pamh, retval)); } pam_passwd = NULL; /* Unset pam_passwd */ @@ -854,8 +805,8 @@ recv_and_check_password_packet(Port *port) return STATUS_EOF; } - elog(DEBUG5, "received password packet with len=%d, pw=%s\n", - len, buf.data); + elog(DEBUG5, "received password packet with len=%d, pw=%s", + len, buf.data); result = checkPassword(port, port->user, buf.data); pfree(buf.data); @@ -907,7 +858,7 @@ old_be_recvauth(Port *port) break; default: - fprintf(stderr, "Invalid startup message type: %u\n", msgtype); + elog(LOG, "Invalid startup message type: %u", msgtype); return STATUS_ERROR; } diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index ccde8020c1..6ab63ddffe 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.43 2002/03/02 21:39:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.44 2002/03/04 01:46:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -273,11 +273,8 @@ md5_crypt_verify(const Port *port, const char *user, const char *pgpass) /* If they encrypt their password, force MD5 */ if (isMD5(passwd) && port->auth_method != uaMD5) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "Password is stored MD5 encrypted. " - "'password' and 'crypt' auth methods cannot be used.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "Password is stored MD5 encrypted. " + "'password' and 'crypt' auth methods cannot be used."); return STATUS_ERROR; } diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 80fe645c1a..b86cb81730 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.79 2002/01/09 19:13:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.80 2002/03/04 01:46:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -269,7 +269,7 @@ parse_hba_auth(List *line, UserAuth *userauth_p, char *auth_arg, * to a database named port->database. If so, return *found_p true * and fill in the auth arguments into the appropriate port fields. * If not, leave *found_p as it was. If the record has a syntax error, - * return *error_p true, after issuing a message to stderr. If no error, + * return *error_p true, after issuing a message to the log. If no error, * leave *error_p as it was. */ static void @@ -391,12 +391,9 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) return; hba_syntax: - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "parse_hba: invalid syntax in pg_hba.conf file at line %d, token \"%s\"\n", - line_number, - line ? (const char *) lfirst(line) : "(end of line)"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "parse_hba: invalid syntax in pg_hba.conf file at line %d, token \"%s\"", + line_number, + line ? (const char *) lfirst(line) : "(end of line)"); *error_p = true; return; @@ -464,13 +461,10 @@ load_hba(void) { /* Old config file exists. Tell this guy he needs to upgrade. */ close(fd); - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "A file exists by the name used for host-based authentication " - "in prior releases of Postgres (%s). The name and format of " - "the configuration file have changed, so this file should be " - "converted.\n", old_conf_file); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "A file exists by the name used for host-based authentication " + "in prior releases of Postgres (%s). The name and format of " + "the configuration file have changed, so this file should be " + "converted.", old_conf_file); } else { @@ -486,11 +480,8 @@ load_hba(void) if (file == NULL) { /* The open of the config file failed. */ - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "load_hba: Unable to open authentication config file \"%s\": %s\n", - conf_file, strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "load_hba: Unable to open authentication config file \"%s\": %m", + conf_file); } else { @@ -553,12 +544,9 @@ parse_ident_usermap(List *line, const char *usermap_name, const char *pg_user, return; ident_syntax: - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "parse_ident_usermap: invalid syntax in pg_ident.conf file at line %d, token \"%s\"\n", - line_number, - line ? (const char *) lfirst(line) : "(end of line)"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "parse_ident_usermap: invalid syntax in pg_ident.conf file at line %d, token \"%s\"", + line_number, + line ? (const char *) lfirst(line) : "(end of line)"); *error_p = true; return; @@ -588,13 +576,10 @@ check_ident_usermap(const char *usermap_name, if (usermap_name[0] == '\0') { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "check_ident_usermap: hba configuration file does not " - "have the usermap field filled in in the entry that pertains " - "to this connection. That field is essential for Ident-based " - "authentication.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "check_ident_usermap: hba configuration file does not " + "have the usermap field filled in in the entry that pertains " + "to this connection. That field is essential for Ident-based " + "authentication."); found_entry = false; } else if (strcmp(usermap_name, "sameuser") == 0) @@ -641,11 +626,8 @@ load_ident(void) if (file == NULL) { /* The open of the map file failed. */ - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "load_ident: Unable to open usermap file \"%s\": %s\n", - map_file, strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "load_ident: Unable to open usermap file \"%s\": %m", + map_file); } else { @@ -766,11 +748,7 @@ ident_inet(const struct in_addr remote_ip_addr, sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock_fd == -1) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "Failed to create socket on which to talk to Ident server. " - "socket() returned errno = %s (%d)\n", strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "Failed to create socket on which to talk to Ident server: %m"); ident_return = false; } else @@ -803,14 +781,14 @@ ident_inet(const struct in_addr remote_ip_addr, } if (rc != 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "Unable to connect to Ident server on the host which is " - "trying to connect to Postgres " - "(IP address %s, Port %d). " - "errno = %s (%d)\n", - inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + /* save_errno is in case inet_ntoa changes errno */ + int save_errno = errno; + + elog(LOG, "Unable to connect to Ident server on the host which is " + "trying to connect to Postgres " + "(IP address %s, Port %d): %s", + inet_ntoa(remote_ip_addr), IDENT_PORT, + strerror(save_errno)); ident_return = false; } else @@ -826,15 +804,13 @@ ident_inet(const struct in_addr remote_ip_addr, } while (rc < 0 && errno == EINTR); if (rc < 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "Unable to send query to Ident server on the host which is " - "trying to connect to Postgres (Host %s, Port %d)," - "even though we successfully connected to it. " - "errno = %s (%d)\n", - inet_ntoa(remote_ip_addr), IDENT_PORT, - strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + int save_errno = errno; + + elog(LOG, "Unable to send query to Ident server on the host which is " + "trying to connect to Postgres (Host %s, Port %d), " + "even though we successfully connected to it: %s", + inet_ntoa(remote_ip_addr), IDENT_PORT, + strerror(save_errno)); ident_return = false; } else @@ -845,16 +821,14 @@ ident_inet(const struct in_addr remote_ip_addr, sizeof(ident_response) - 1, 0); if (rc < 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "Unable to receive response from Ident server " - "on the host which is " - "trying to connect to Postgres (Host %s, Port %d)," - "even though we successfully sent our query to it. " - "errno = %s (%d)\n", - inet_ntoa(remote_ip_addr), IDENT_PORT, - strerror(errno), errno); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + int save_errno = errno; + + elog(LOG, "Unable to receive response from Ident server " + "on the host which is " + "trying to connect to Postgres (Host %s, Port %d), " + "even though we successfully sent our query to it: %s", + inet_ntoa(remote_ip_addr), IDENT_PORT, + strerror(save_errno)); ident_return = false; } else @@ -891,11 +865,7 @@ ident_unix(int sock, char *ident_user) so_len != sizeof(peercred)) { /* We didn't get a valid credentials struct. */ - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "ident_unix: error receiving credentials: %s\n", - strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "ident_unix: error receiving credentials: %m"); return false; } @@ -903,10 +873,8 @@ ident_unix(int sock, char *ident_user) if (pass == NULL) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "ident_unix: unknown local user with uid %d\n", peercred.uid); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "ident_unix: unknown local user with uid %d", + (int) peercred.uid); return false; } @@ -962,11 +930,7 @@ ident_unix(int sock, char *ident_user) cmsg->cmsg_len < sizeof(cmsgmem) || cmsg->cmsg_type != SCM_CREDS) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "ident_unix: error receiving credentials: %s\n", - strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "ident_unix: error receiving credentials: %m"); return false; } @@ -975,11 +939,8 @@ ident_unix(int sock, char *ident_user) pw = getpwuid(cred->cruid); if (pw == NULL) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "ident_unix: unknown local user with uid %d\n", - cred->cruid); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "ident_unix: unknown local user with uid %d", + (int) cred->cruid); return false; } @@ -988,10 +949,7 @@ ident_unix(int sock, char *ident_user) return true; #else - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "'ident' auth is not supported on local connections on this platform\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "'ident' auth is not supported on local connections on this platform"); return false; #endif diff --git a/src/backend/libpq/password.c b/src/backend/libpq/password.c index 96415ae4e7..f8490f8bd5 100644 --- a/src/backend/libpq/password.c +++ b/src/backend/libpq/password.c @@ -2,7 +2,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: password.c,v 1.40 2001/10/25 05:49:30 momjian Exp $ + * $Id: password.c,v 1.41 2002/03/04 01:46:03 tgl Exp $ * */ @@ -36,11 +36,8 @@ verify_password(const Port *port, const char *user, const char *password) pw_file = AllocateFile(pw_file_fullname, PG_BINARY_R); if (!pw_file) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "verify_password: Unable to open password file \"%s\": %s\n", - pw_file_fullname, strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "verify_password: Unable to open password file \"%s\": %m", + pw_file_fullname); pfree(pw_file_fullname); @@ -96,11 +93,8 @@ verify_password(const Port *port, const char *user, const char *password) return STATUS_OK; } - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "verify_password: password mismatch for '%s'.\n", - user); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "verify_password: password mismatch for '%s'", + user); return STATUS_ERROR; } @@ -108,11 +102,8 @@ verify_password(const Port *port, const char *user, const char *password) FreeFile(pw_file); - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "verify_password: user '%s' not found in password file.\n", - user); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "verify_password: user '%s' not found in password file", + user); return STATUS_ERROR; } diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 8fee496e35..df55fad678 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -29,7 +29,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.c,v 1.127 2002/03/02 21:39:26 momjian Exp $ + * $Id: pqcomm.c,v 1.128 2002/03/04 01:46:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -189,11 +189,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, if ((fd = socket(family, SOCK_STREAM, 0)) < 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: StreamServerPort: socket() failed: %s\n", - strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "StreamServerPort: socket() failed: %m"); return STATUS_ERROR; } @@ -202,11 +198,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one))) == -1) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: StreamServerPort: setsockopt(SO_REUSEADDR) failed: %s\n", - strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "StreamServerPort: setsockopt(SO_REUSEADDR) failed: %m"); return STATUS_ERROR; } } @@ -247,11 +239,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, hp = gethostbyname(hostName); if ((hp == NULL) || (hp->h_addrtype != AF_INET)) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: StreamServerPort: gethostbyname(%s) failed\n", - hostName); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "StreamServerPort: gethostbyname(%s) failed", + hostName); return STATUS_ERROR; } memmove((char *) &(saddr.in.sin_addr), (char *) hp->h_addr, @@ -265,21 +254,16 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, err = bind(fd, (struct sockaddr *) & saddr.sa, len); if (err < 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: StreamServerPort: bind() failed: %s\n" - "\tIs another postmaster already running on port %d?\n", - strerror(errno), (int) portNumber); if (family == AF_UNIX) - snprintf(PQerrormsg + strlen(PQerrormsg), - PQERRORMSG_LENGTH - strlen(PQerrormsg), - "\tIf not, remove socket node (%s) and retry.\n", - sock_path); + elog(LOG, "StreamServerPort: bind() failed: %m\n" + "\tIs another postmaster already running on port %d?\n" + "\tIf not, remove socket node (%s) and retry.", + (int) portNumber, sock_path); else - snprintf(PQerrormsg + strlen(PQerrormsg), - PQERRORMSG_LENGTH - strlen(PQerrormsg), - "\tIf not, wait a few seconds and retry.\n"); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "StreamServerPort: bind() failed: %m\n" + "\tIs another postmaster already running on port %d?\n" + "\tIf not, wait a few seconds and retry.", + (int) portNumber); return STATUS_ERROR; } @@ -315,33 +299,24 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, gr = getgrnam(Unix_socket_group); if (!gr) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: no such group '%s'\n", - Unix_socket_group); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "No such group as '%s'", + Unix_socket_group); return STATUS_ERROR; } gid = gr->gr_gid; } if (chown(sock_path, -1, gid) == -1) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: could not set group of %s: %s\n", - sock_path, strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "Could not set group of %s: %m", + sock_path); return STATUS_ERROR; } } if (chmod(sock_path, Unix_socket_permissions) == -1) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: could not set permissions on %s: %s\n", - sock_path, strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "Could not set permissions on %s: %m", + sock_path); return STATUS_ERROR; } } @@ -359,11 +334,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, err = listen(fd, maxconn); if (err < 0) { - snprintf(PQerrormsg, PQERRORMSG_LENGTH, - "FATAL: StreamServerPort: listen() failed: %s\n", - strerror(errno)); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); + elog(LOG, "StreamServerPort: listen() failed: %m"); return STATUS_ERROR; } @@ -380,10 +351,6 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, * the Postmaster uses select() to tell when the server master * socket is ready for accept(). * - * NB: this can NOT call elog() because it is invoked in the postmaster, - * not in standard backend context. If we get an error, the best we can do - * is log it to stderr. - * * RETURNS: STATUS_OK or STATUS_ERROR */ int @@ -507,15 +474,15 @@ pq_recvbuf(void) * Careful: an elog() that tries to write to the client * would cause recursion to here, leading to stack overflow * and core dump! This message must go *only* to the postmaster - * log. elog(LOG) is presently safe. + * log. */ - elog(LOG, "pq_recvbuf: recv() failed: %m"); + elog(COMMERROR, "pq_recvbuf: recv() failed: %m"); return EOF; } if (r == 0) { /* as above, only write to postmaster log */ - elog(LOG, "pq_recvbuf: unexpected EOF on client connection"); + elog(COMMERROR, "pq_recvbuf: unexpected EOF on client connection"); return EOF; } /* r contains number of bytes read, so just incr length */ @@ -680,7 +647,7 @@ pq_flush(void) * Careful: an elog() that tries to write to the client * would cause recursion to here, leading to stack overflow * and core dump! This message must go *only* to the postmaster - * log. elog(LOG) is presently safe. + * log. * * If a client disconnects while we're in the midst of output, * we might write quite a bit of data before we get to a safe @@ -689,7 +656,7 @@ pq_flush(void) if (errno != last_reported_send_errno) { last_reported_send_errno = errno; - elog(LOG, "pq_flush: send() failed: %m"); + elog(COMMERROR, "pq_flush: send() failed: %m"); } /* @@ -723,7 +690,7 @@ pq_eof(void) if (res < 0) { /* can log to postmaster log only */ - elog(LOG, "pq_eof: recv() failed: %m"); + elog(COMMERROR, "pq_eof: recv() failed: %m"); return EOF; } if (res == 0) diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c index 27cfa0704b..f886ff4240 100644 --- a/src/backend/libpq/pqformat.c +++ b/src/backend/libpq/pqformat.c @@ -16,7 +16,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqformat.c,v 1.19 2001/12/04 20:57:22 tgl Exp $ + * $Id: pqformat.c,v 1.20 2002/03/04 01:46:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -284,7 +284,7 @@ pq_getint(int *result, int b) * if we elog(ERROR) here, we will lose sync with the * frontend, so just complain to postmaster log instead... */ - fprintf(stderr, "pq_getint: unsupported size %d\n", b); + elog(COMMERROR, "pq_getint: unsupported size %d", b); status = EOF; *result = 0; break; diff --git a/src/backend/libpq/util.c b/src/backend/libpq/util.c deleted file mode 100644 index 4ddf17d59b..0000000000 --- a/src/backend/libpq/util.c +++ /dev/null @@ -1,77 +0,0 @@ -/*------------------------------------------------------------------------- - * - * util.c - * general routines for backend libpq modules - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * $Header: /cvsroot/pgsql/src/backend/libpq/Attic/util.c,v 1.18 2001/10/25 05:49:30 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -/* - * UTILITY ROUTINES - * pqdebug - send a string to the debugging output port - * PQtrace - turn on pqdebug() tracing - * PQuntrace - turn off pqdebug() tracing - */ - -#include "postgres.h" - -#include "libpq/libpq.h" - - -/* ---------------- - * global variables for backend libpq - * ---------------- - */ -char PQerrormsg[PQERRORMSG_LENGTH]; - -/* - * These are not really global --- they are referred to nowhere else. - * We declare them as global symbols to make them easier to set in a debugger. - */ - -int PQtracep = 0; /* 1 to print out debugging messages */ - -FILE *debug_port = (FILE *) NULL; - -/* ---------------------------------------------------------------- - * PQ utility routines - * ---------------------------------------------------------------- - */ - -void -pqdebug(char *fmt, char *msg) -{ - if (!fmt) - return; - - if (PQtracep) - { - /* - * if nothing else was suggested default to stderr - */ - if (!debug_port) - debug_port = stderr; - fprintf(debug_port, fmt, msg); - fprintf(debug_port, "\n"); - } -} - -/* -------------------------------- - * PQtrace() / PQuntrace() - * -------------------------------- - */ -void -PQtrace() -{ - PQtracep = 1; -} - -void -PQuntrace() -{ - PQtracep = 0; -} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index fc86357fcb..02f6d576c6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.269 2002/03/02 21:39:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.270 2002/03/04 01:46:03 tgl Exp $ * * NOTES * @@ -211,6 +211,8 @@ static int Shutdown = NoShutdown; static bool FatalError = false; /* T if recovering from backend crash */ +bool ClientAuthInProgress = false; /* T during new-client authentication */ + /* * State for assigning random salts and cancel keys. * Also, the global MyCancelKey passes the cancel key assigned to a given @@ -240,7 +242,8 @@ static void reaper(SIGNAL_ARGS); static void sigusr1_handler(SIGNAL_ARGS); static void dummy_handler(SIGNAL_ARGS); static void CleanupProc(int pid, int exitstatus); -static void LogChildExit(const char *procname, int pid, int exitstatus); +static void LogChildExit(int lev, const char *procname, + int pid, int exitstatus); static int DoBackend(Port *port); static void ExitPostmaster(int status); static void usage(const char *); @@ -715,7 +718,7 @@ PostmasterMain(int argc, char *argv[]) /* * Reset whereToSendOutput from Debug (its starting state) to None. - * This prevents elog from sending messages to stderr unless the + * This prevents elog from sending log messages to stderr unless the * syslog/stderr switch permits. We don't do this until the * postmaster is fully launched, since startup failures may as well be * reported to stderr. @@ -1105,8 +1108,7 @@ ProcessStartupPacket(Port *port, bool SSLdone) #endif if (send(port->sock, &SSLok, 1, 0) != 1) { - elog(LOG, "failed to send SSL negotiation response: %s", - strerror(errno)); + elog(LOG, "failed to send SSL negotiation response: %m"); return STATUS_ERROR; /* close the connection */ } @@ -1384,6 +1386,7 @@ SIGHUP_handler(SIGNAL_ARGS) if (Shutdown <= SmartShutdown) { + elog(LOG, "Received SIGHUP, reloading configuration files"); SignalChildren(SIGHUP); ProcessConfigFile(PGC_SIGHUP); load_hba_and_ident(); @@ -1527,7 +1530,7 @@ reaper(SIGNAL_ARGS) PG_SETMASK(&BlockSig); - elog(DEBUG1, "reaping dead processes"); + elog(DEBUG3, "reaping dead processes"); #ifdef HAVE_WAITPID while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { @@ -1544,7 +1547,7 @@ reaper(SIGNAL_ARGS) */ if (pgstat_ispgstat(pid)) { - LogChildExit(gettext("statistics collector process"), + LogChildExit(LOG, gettext("statistics collector process"), pid, exitstatus); pgstat_start(); continue; @@ -1557,7 +1560,7 @@ reaper(SIGNAL_ARGS) { if (exitstatus != 0) { - LogChildExit(gettext("shutdown process"), + LogChildExit(LOG, gettext("shutdown process"), pid, exitstatus); ExitPostmaster(1); } @@ -1568,7 +1571,7 @@ reaper(SIGNAL_ARGS) { if (exitstatus != 0) { - LogChildExit(gettext("startup process"), + LogChildExit(LOG, gettext("startup process"), pid, exitstatus); elog(LOG, "aborting startup due to startup process failure"); ExitPostmaster(1); @@ -1649,7 +1652,7 @@ CleanupProc(int pid, *next; Backend *bp; - LogChildExit(gettext("child process"), pid, exitstatus); + LogChildExit(DEBUG1, gettext("child process"), pid, exitstatus); /* * If a backend dies in an ugly way (i.e. exit status not 0) then we @@ -1694,7 +1697,7 @@ CleanupProc(int pid, /* Make log entry unless we did so already */ if (!FatalError) { - LogChildExit(gettext("server process"), pid, exitstatus); + LogChildExit(LOG, gettext("server process"), pid, exitstatus); elog(LOG, "terminating any other active server processes"); } @@ -1753,20 +1756,20 @@ CleanupProc(int pid, * Log the death of a child process. */ static void -LogChildExit(const char *procname, int pid, int exitstatus) +LogChildExit(int lev, const char *procname, int pid, int exitstatus) { /* * translator: the first %s in these messages is a noun phrase * describing a child process, such as "server process" */ if (WIFEXITED(exitstatus)) - elog(LOG, "%s (pid %d) exited with exit code %d", + elog(lev, "%s (pid %d) exited with exit code %d", procname, pid, WEXITSTATUS(exitstatus)); else if (WIFSIGNALED(exitstatus)) - elog(LOG, "%s (pid %d) was terminated by signal %d", + elog(lev, "%s (pid %d) was terminated by signal %d", procname, pid, WTERMSIG(exitstatus)); else - elog(LOG, "%s (pid %d) exited with unexpected status %d", + elog(lev, "%s (pid %d) exited with unexpected status %d", procname, pid, exitstatus); } @@ -2008,6 +2011,8 @@ DoBackend(Port *port) IsUnderPostmaster = true; /* we are a postmaster subprocess now */ + ClientAuthInProgress = true; /* limit visibility of log messages */ + /* We don't want the postmaster's proc_exit() handlers */ on_exit_reset(); @@ -2218,8 +2223,10 @@ DoBackend(Port *port) */ elog(DEBUG2, "%s child[%d]: starting with (", progname, MyProcPid); for (i = 0; i < ac; ++i) - elog(DEBUG2, "%s ", av[i]); - elog(DEBUG2, ")\n"); + elog(DEBUG2, "\t%s", av[i]); + elog(DEBUG2, ")"); + + ClientAuthInProgress = false; /* client_min_messages is active now */ return (PostgresMain(ac, av, port->user)); } @@ -2580,17 +2587,15 @@ SSDataBase(int xlop) switch (xlop) { case BS_XLOG_STARTUP: - elog(LOG, "could not launch startup process (fork failure): %s", - strerror(errno)); + elog(LOG, "could not launch startup process (fork failure): %m"); break; case BS_XLOG_CHECKPOINT: - elog(LOG, "could not launch checkpoint process (fork failure): %s", - strerror(errno)); + elog(LOG, "could not launch checkpoint process (fork failure): %m"); break; case BS_XLOG_SHUTDOWN: + elog(LOG, "could not launch shutdown process (fork failure): %m"); + break; default: - elog(LOG, "could not launch shutdown process (fork failure): %s", - strerror(errno)); break; } @@ -2673,7 +2678,10 @@ CreateOptsFile(int argc, char *argv[]) return true; } - +/* + * This should be used only for reporting "interactive" errors (ie, errors + * during startup. Once the postmaster is launched, use elog. + */ static void postmaster_error(const char *fmt,...) { diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index f68a2f88fb..57d0976d90 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.252 2002/03/02 21:39:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.253 2002/03/04 01:46:03 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1647,7 +1647,7 @@ PostgresMain(int argc, char *argv[], const char *username) DBName = argv[optind]; else if ((DBName = username) == NULL) { - elog(NOTICE, "%s: user name undefined and no database specified\n", + elog(NOTICE, "%s: user name undefined and no database specified", argv[0]); proc_exit(1); } @@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.252 $ $Date: 2002/03/02 21:39:31 $\n"); + puts("$Revision: 1.253 $ $Date: 2002/03/04 01:46:03 $\n"); } /* @@ -1906,6 +1906,13 @@ PostgresMain(int argc, char *argv[], const char *username) if (HandleFunctionRequest() == EOF) { /* lost frontend connection during F message input */ + /* + * Reset whereToSendOutput to prevent elog from attempting + * to send any more messages to client. + */ + if (whereToSendOutput == Remote) + whereToSendOutput = None; + proc_exit(0); } @@ -1949,14 +1956,19 @@ PostgresMain(int argc, char *argv[], const char *username) } break; - /* ---------------- + /* * 'X' means that the frontend is closing down the socket. * EOF means unexpected loss of frontend connection. * Either way, perform normal shutdown. - * ---------------- */ case 'X': case EOF: + /* + * Reset whereToSendOutput to prevent elog from attempting + * to send any more messages to client. + */ + if (whereToSendOutput == Remote) + whereToSendOutput = None; /* * NOTE: if you are tempted to add more code here, DON'T! @@ -2122,7 +2134,7 @@ assertTest(int val) if (assert_enabled) { /* val != 0 should be trapped by previous Assert */ - elog(INFO, "Assert test successfull (val = %d)", val); + elog(INFO, "Assert test successful (val = %d)", val); } else elog(INFO, "Assert checking is disabled (val = %d)", val); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index d466a48d2d..69e6fd52db 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.92 2002/03/02 21:39:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.93 2002/03/04 01:46:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -38,15 +38,13 @@ #include "mb/pg_wchar.h" #endif -#define DEFAULT_SERVER_MIN_MESSAGES_STR "notice" int server_min_messages; char *server_min_messages_str = NULL; -const char server_min_messages_str_default[] = DEFAULT_SERVER_MIN_MESSAGES_STR; +const char server_min_messages_str_default[] = "notice"; -#define DEFAULT_CLIENT_MIN_MESSAGES_STR "info" int client_min_messages; char *client_min_messages_str = NULL; -const char client_min_messages_str_default[] = DEFAULT_CLIENT_MIN_MESSAGES_STR; +const char client_min_messages_str_default[] = "info"; #ifdef ENABLE_SYSLOG /* @@ -106,7 +104,6 @@ void elog(int lev, const char *fmt,...) { va_list ap; - /* * The expanded format and final output message are dynamically * allocated if necessary, but not if they fit in the "reasonable @@ -128,59 +125,20 @@ elog(int lev, const char *fmt,...) char msg_fixedbuf[256]; char *fmt_buf = fmt_fixedbuf; char *msg_buf = msg_fixedbuf; - - /* for COPY line numbers */ - char copylineno_buf[32]; - + char copylineno_buf[32]; /* for COPY line numbers */ const char *errorstr; const char *prefix; const char *cp; char *bp; size_t space_needed; + size_t timestamp_size; /* prefix len for timestamp+pid */ bool output_to_server = false; bool output_to_client = false; - /* size of the prefix needed for timestamp and pid, if enabled */ - size_t timestamp_size; - /* Check for old elog calls. Codes were renumbered in 7.3. 2002-02-24 */ if (lev < DEBUG5) elog(FATAL, "Pre-7.3 object file made an elog() call. Recompile."); - if (Use_syslog <= 1 || whereToSendOutput == Debug) - { - if (lev == LOG) - { - if (server_min_messages == LOG) - output_to_server = true; - else if (server_min_messages < FATAL) - output_to_server = true; - } - /* lev != LOG */ - else - { - if (server_min_messages == LOG) - { - if (lev >= FATAL) - output_to_server = true; - } - /* Neither is LOG */ - else if (lev >= server_min_messages) - output_to_server = true; - } - } - - if (lev >= client_min_messages && whereToSendOutput == Remote) - output_to_client = true; - - /* optimization to prevent work for messages that would never be output */ - if (lev < ERROR && Use_syslog < 1 && - output_to_server == false && output_to_client == false) - return; - - /* Save error str before calling any function that might change errno */ - errorstr = useful_strerror(errno); - /* * Convert initialization errors into fatal errors. This is probably * redundant, because Warn_restart_ready won't be set anyway. @@ -192,12 +150,60 @@ elog(int lev, const char *fmt,...) * If we are inside a critical section, all errors become PANIC * errors. See miscadmin.h. */ - if (lev == ERROR || lev == FATAL) + if (lev >= ERROR) { if (CritSectionCount > 0) lev = PANIC; } + /* Determine whether message is enabled for server log output */ + /* Complicated because LOG is sorted out-of-order for this purpose */ + if (lev == LOG || lev == COMMERROR) + { + if (server_min_messages == LOG) + output_to_server = true; + else if (server_min_messages < FATAL) + output_to_server = true; + } + else + { + /* lev != LOG */ + if (server_min_messages == LOG) + { + if (lev >= FATAL) + output_to_server = true; + } + /* Neither is LOG */ + else if (lev >= server_min_messages) + output_to_server = true; + } + + /* Determine whether message is enabled for client output */ + if (whereToSendOutput == Remote && lev != COMMERROR) + { + /* + * client_min_messages is honored only after we complete the + * authentication handshake. This is required both for security + * reasons and because many clients can't handle NOTICE messages + * during authentication. + */ + if (ClientAuthInProgress) + output_to_client = (lev >= ERROR); + else + output_to_client = (lev >= client_min_messages); + } + + /* Skip formatting effort if non-error message will not be output */ + if (lev < ERROR && !output_to_server && !output_to_client) + return; + + /* Save error str before calling any function that might change errno */ + errorstr = useful_strerror(errno); + + /* Internationalize the error format string */ + fmt = gettext(fmt); + + /* Begin formatting by determining prefix information */ prefix = elog_message_prefix(lev); timestamp_size = 0; @@ -206,8 +212,6 @@ elog(int lev, const char *fmt,...) if (Log_pid) timestamp_size += PID_SIZE; - fmt = gettext(fmt); - /* * Set up the expanded format, consisting of the prefix string plus * input format, with any %m replaced by strerror() string (since @@ -221,7 +225,7 @@ elog(int lev, const char *fmt,...) { /* * Prints the failure line of the COPY. Wow, what a hack! bjm - * Translators: Error message will be truncated at 31 characters. + * Translator: Error message will be truncated at 31 characters. */ snprintf(copylineno_buf, 32, gettext("copy: line %d, "), copy_lineno); space_needed += strlen(copylineno_buf); @@ -234,7 +238,7 @@ elog(int lev, const char *fmt,...) { /* We're up against it, convert to out-of-memory error */ fmt_buf = fmt_fixedbuf; - if (lev != FATAL && lev != PANIC) + if (lev < ERROR) { lev = ERROR; prefix = elog_message_prefix(lev); @@ -263,7 +267,7 @@ elog(int lev, const char *fmt,...) if (copy_lineno) { strcat(fmt_buf, copylineno_buf); - if (lev == ERROR || lev == FATAL || lev == PANIC) + if (lev >= ERROR) copy_lineno = 0; } @@ -331,7 +335,7 @@ elog(int lev, const char *fmt,...) { /* We're up against it, convert to out-of-memory error */ msg_buf = msg_fixedbuf; - if (lev != FATAL && lev != PANIC) + if (lev < ERROR) { lev = ERROR; prefix = elog_message_prefix(lev); @@ -353,7 +357,7 @@ elog(int lev, const char *fmt,...) #ifdef ENABLE_SYSLOG /* Write to syslog, if enabled */ - if (Use_syslog >= 1) + if (output_to_server && Use_syslog >= 1) { int syslog_level; @@ -367,6 +371,7 @@ elog(int lev, const char *fmt,...) syslog_level = LOG_DEBUG; break; case LOG: + case COMMERROR: case INFO: syslog_level = LOG_INFO; break; @@ -392,11 +397,11 @@ elog(int lev, const char *fmt,...) /* syslog doesn't want a trailing newline, but other destinations do */ strcat(msg_buf, "\n"); - /* Write to server logs or server terminal */ - if (output_to_server) + /* Write to stderr, if enabled */ + if (output_to_server && (Use_syslog <= 1 || whereToSendOutput == Debug)) write(2, msg_buf, strlen(msg_buf)); - /* Should we output to the client too? */ + /* Send to client, if enabled */ if (output_to_client) { /* Send IPC message to the front-end program */ @@ -441,6 +446,13 @@ elog(int lev, const char *fmt,...) /* Prevent immediate interrupt while entering error recovery */ ImmediateInterruptOK = false; + /* + * If we just reported a startup failure, the client will + * disconnect on receiving it, so don't send any more to the client. + */ + if (!Warn_restart_ready && whereToSendOutput == Remote) + whereToSendOutput = None; + /* * For a FATAL error, we let proc_exit clean up and exit. * @@ -482,7 +494,7 @@ elog(int lev, const char *fmt,...) siglongjmp(Warn_restart, 1); } - if (lev == FATAL || lev == PANIC) + if (lev == PANIC) { /* * Serious crash time. Postmaster will observe nonzero process @@ -494,7 +506,7 @@ elog(int lev, const char *fmt,...) ImmediateInterruptOK = false; fflush(stdout); fflush(stderr); - proc_exit(lev); + proc_exit(2); } /* We reach here if lev <= NOTICE. OK to return to caller. */ @@ -774,7 +786,8 @@ useful_strerror(int errnum) * translator: This string will be truncated at 47 characters * expanded. */ - snprintf(errorstr_buf, 48, gettext("operating system error %d"), errnum); + snprintf(errorstr_buf, 48, gettext("operating system error %d"), + errnum); str = errorstr_buf; } @@ -798,6 +811,7 @@ elog_message_prefix(int lev) prefix = gettext("DEBUG: "); break; case LOG: + case COMMERROR: prefix = gettext("LOG: "); break; case INFO: @@ -832,7 +846,7 @@ check_server_min_messages(const char *lev) if (strcasecmp(lev, "debug") == 0 || strcasecmp(lev, "debug1") == 0 || strcasecmp(lev, "debug2") == 0 || - strcasecmp(lev, "debub3") == 0 || + strcasecmp(lev, "debug3") == 0 || strcasecmp(lev, "debug4") == 0 || strcasecmp(lev, "debug5") == 0 || strcasecmp(lev, "log") == 0 || @@ -848,7 +862,9 @@ check_server_min_messages(const char *lev) void assign_server_min_messages(const char *lev) { - if (strcasecmp(lev, "debug1") == 0) + if (strcasecmp(lev, "debug") == 0) + server_min_messages = DEBUG1; + else if (strcasecmp(lev, "debug1") == 0) server_min_messages = DEBUG1; else if (strcasecmp(lev, "debug2") == 0) server_min_messages = DEBUG2; @@ -895,7 +911,9 @@ check_client_min_messages(const char *lev) void assign_client_min_messages(const char *lev) { - if (strcasecmp(lev, "debug1") == 0) + if (strcasecmp(lev, "debug") == 0) + client_min_messages = DEBUG1; + else if (strcasecmp(lev, "debug1") == 0) client_min_messages = DEBUG1; else if (strcasecmp(lev, "debug2") == 0) client_min_messages = DEBUG2; @@ -917,5 +935,3 @@ assign_client_min_messages(const char *lev) /* Can't get here unless guc.c screwed up */ elog(ERROR, "bogus client_min_messages %s", lev); } - - diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index a68d546d42..1b5de24dd7 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq.h,v 1.49 2001/12/04 19:40:17 tgl Exp $ + * $Id: libpq.h,v 1.50 2002/03/04 01:46:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,17 +37,6 @@ typedef struct } u; } PQArgBlock; -/* - * PQerrormsg[] is used only for error messages generated within backend - * libpq, none of which are remarkably long. Note that this length should - * NOT be taken as any indication of the maximum error message length that - * the backend can create! elog() can in fact produce extremely long messages. - */ - -#define PQERRORMSG_LENGTH 1024 - -extern char PQerrormsg[PQERRORMSG_LENGTH]; /* in libpq/util.c */ - /* * External functions. */ @@ -71,11 +60,4 @@ extern int pq_putmessage(char msgtype, const char *s, size_t len); extern void pq_startcopyout(void); extern void pq_endcopyout(bool errorAbort); -/* - * prototypes for functions in util.c - */ -extern void pqdebug(char *fmt, char *msg); -extern void PQtrace(void); -extern void PQuntrace(void); - #endif /* LIBPQ_H */ diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 8872d54768..4fb6447392 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: miscadmin.h,v 1.100 2002/03/02 21:39:34 momjian Exp $ + * $Id: miscadmin.h,v 1.101 2002/03/04 01:46:04 tgl Exp $ * * NOTES * some of the information in this file should be moved to @@ -104,6 +104,9 @@ extern void ProcessInterrupts(void); /* * from postmaster/postmaster.c */ +extern bool IsUnderPostmaster; +extern bool ClientAuthInProgress; + extern int PostmasterMain(int argc, char *argv[]); extern void ClosePostmasterPorts(bool pgstat_too); @@ -127,8 +130,6 @@ extern char pg_pathname[]; */ extern DLLIMPORT Oid MyDatabaseId; -extern bool IsUnderPostmaster; - /* Date/Time Configuration * * Constants to pass info from runtime environment: diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 9be3d2a19a..0b72865e39 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: elog.h,v 1.31 2002/03/02 21:39:35 momjian Exp $ + * $Id: elog.h,v 1.32 2002/03/04 01:46:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,25 +15,29 @@ #define ELOG_H /* Error level codes */ -#define DEBUG5 10 /* sent only to server logs, label DEBUG */ -#define DEBUG4 11 /* logs in decreasing detail */ +#define DEBUG5 10 /* Debugging messages, in categories + * of decreasing detail. */ +#define DEBUG4 11 #define DEBUG3 12 #define DEBUG2 13 #define DEBUG1 14 -#define LOG 15 /* sent only to server logs by default, - * label LOG. */ -#define INFO 16 /* sent only to client by default, for - * informative messages that are part of - * normal query operation. */ -#define NOTICE 17 /* sent to client and server by default, - * important messages, for unusual cases that +#define LOG 15 /* Server operational history messages; + * sent only to server log by default. */ +#define COMMERROR 16 /* Client communication problems; same as + * LOG for server reporting, but never ever + * try to send to client. */ +#define INFO 17 /* Informative messages that are part of + * normal query operation; sent only to + * client by default. */ +#define NOTICE 18 /* Important messages, for unusual cases that * should be reported but are not serious - * enough to abort the query. */ -#define ERROR 18 /* user error - return to known state */ -#define FATAL 19 /* fatal error - abort process */ -#define PANIC 20 /* take down the other backends with me */ + * enough to abort the query. Sent to client + * and server log by default. */ +#define ERROR 19 /* user error - return to known state */ +#define FATAL 20 /* fatal error - abort process */ +#define PANIC 21 /* take down the other backends with me */ -/*#define DEBUG DEBUG5*/ /* Backward compatibility with pre-7.3 */ +/*#define DEBUG DEBUG1*/ /* Backward compatibility with pre-7.3 */ /* Configurable parameters */ #ifdef ENABLE_SYSLOG