fe-connect.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,647 行 · 第 1/5 页
C
2,647 行
{ closePGconn(conn); freePGconn(conn); }}/* PQreset : resets the connection to the backend closes the existing connection and makes a new one*/voidPQreset(PGconn *conn){ if (conn) { closePGconn(conn); if (connectDBStart(conn)) (void) connectDBComplete(conn); }}/* PQresetStart : resets the connection to the backend closes the existing connection and makes a new one Returns 1 on success, 0 on failure.*/intPQresetStart(PGconn *conn){ if (conn) { closePGconn(conn); return connectDBStart(conn); } return 0;}/* PQresetPoll : resets the connection to the backend closes the existing connection and makes a new one*/PostgresPollingStatusTypePQresetPoll(PGconn *conn){ if (conn) return PQconnectPoll(conn); return PGRES_POLLING_FAILED;}/* * PQrequestCancel: attempt to request cancellation of the current operation. * * The return value is TRUE if the cancel request was successfully * dispatched, FALSE if not (in which case conn->errorMessage is set). * Note: successful dispatch is no guarantee that there will be any effect at * the backend. The application must read the operation result as usual. * * XXX it was a bad idea to have the error message returned in * conn->errorMessage, since it could overwrite a message already there. * Would be better to return it in a char array passed by the caller. * * CAUTION: we want this routine to be safely callable from a signal handler * (for example, an application might want to call it in a SIGINT handler). * This means we cannot use any C library routine that might be non-reentrant. * malloc/free are often non-reentrant, and anything that might call them is * just as dangerous. We avoid sprintf here for that reason. Building up * error messages with strcpy/strcat is tedious but should be quite safe. * We also save/restore errno in case the signal handler support doesn't. * * NOTE: this routine must not generate any error message longer than * INITIAL_EXPBUFFER_SIZE (currently 256), since we dare not try to * expand conn->errorMessage! */intPQrequestCancel(PGconn *conn){ int save_errno = SOCK_ERRNO; int tmpsock = -1; char sebuf[256]; struct { uint32 packetlen; CancelRequestPacket cp; } crp; /* Check we have an open connection */ if (!conn) return FALSE; if (conn->sock < 0) { strcpy(conn->errorMessage.data, "PQrequestCancel() -- connection is not open\n"); conn->errorMessage.len = strlen(conn->errorMessage.data);#ifdef WIN32 WSASetLastError(save_errno);#else errno = save_errno;#endif return FALSE; } /* * We need to open a temporary connection to the postmaster. Use the * information saved by connectDB to do this with only kernel calls. */ if ((tmpsock = socket(conn->raddr.addr.ss_family, SOCK_STREAM, 0)) < 0) { strcpy(conn->errorMessage.data, "PQrequestCancel() -- socket() failed: "); goto cancel_errReturn; }retry3: if (connect(tmpsock, (struct sockaddr *) & conn->raddr.addr, conn->raddr.salen) < 0) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry3; strcpy(conn->errorMessage.data, "PQrequestCancel() -- connect() failed: "); goto cancel_errReturn; } /* * We needn't set nonblocking I/O or NODELAY options here. */ /* Create and send the cancel request packet. */ crp.packetlen = htonl((uint32) sizeof(crp)); crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE); crp.cp.backendPID = htonl(conn->be_pid); crp.cp.cancelAuthCode = htonl(conn->be_key);retry4: if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp)) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry4; strcpy(conn->errorMessage.data, "PQrequestCancel() -- send() failed: "); goto cancel_errReturn; } /* * Wait for the postmaster to close the connection, which indicates that * it's processed the request. Without this delay, we might issue another * command only to find that our cancel zaps that command instead of the * one we thought we were canceling. Note we don't actually expect this * read to obtain any data, we are just waiting for EOF to be signaled. */retry5: if (recv(tmpsock, (char *) &crp, 1, 0) < 0) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry5; /* we ignore other error conditions */ } /* All done */ closesocket(tmpsock);#ifdef WIN32 WSASetLastError(save_errno);#else errno = save_errno;#endif return TRUE;cancel_errReturn: strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); strcat(conn->errorMessage.data, "\n"); conn->errorMessage.len = strlen(conn->errorMessage.data); if (tmpsock >= 0) { closesocket(tmpsock);#ifdef WIN32 WSASetLastError(save_errno);#else errno = save_errno;#endif } return FALSE;}/* * pqPacketSend() -- convenience routine to send a message to server. * * pack_type: the single-byte message type code. (Pass zero for startup * packets, which have no message type code.) * * buf, buf_len: contents of message. The given length includes only what * is in buf; the message type and message length fields are added here. * * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise. * SIDE_EFFECTS: may block. * * Note: all messages sent with this routine have a length word, whether * it's protocol 2.0 or 3.0. */intpqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len){ /* Start the message. */ if (pqPutMsgStart(pack_type, true, conn)) return STATUS_ERROR; /* Send the message body. */ if (pqPutnchar(buf, buf_len, conn)) return STATUS_ERROR; /* Finish the message. */ if (pqPutMsgEnd(conn)) return STATUS_ERROR; /* Flush to ensure backend gets it. */ if (pqFlush(conn)) return STATUS_ERROR; return STATUS_OK;}#ifndef SYSCONFDIR#error "You must compile this file with SYSCONFDIR defined."#endif#define MAXBUFSIZE 256static intparseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage){ char *service = conninfo_getval(options, "service"); char *serviceFile = SYSCONFDIR "/pg_service.conf"; bool group_found = false; int linenr = 0, i; /* * We have to special-case the environment variable PGSERVICE here, * since this is and should be called before inserting environment * defaults for other connection options. */ if (service == NULL) service = getenv("PGSERVICE"); if (service != NULL) { FILE *f; char buf[MAXBUFSIZE], *line; f = fopen(serviceFile, "r"); if (f == NULL) { printfPQExpBuffer(errorMessage, "ERROR: Service file '%s' not found\n", serviceFile); return 1; } while ((line = fgets(buf, MAXBUFSIZE - 1, f)) != NULL) { linenr++; if (strlen(line) >= MAXBUFSIZE - 2) { fclose(f); printfPQExpBuffer(errorMessage, "ERROR: line %d too long in service file '%s'\n", linenr, serviceFile); return 2; } /* ignore EOL at end of line */ if (strlen(line) && line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0; /* ignore leading blanks */ while (*line && isspace((unsigned char) line[0])) line++; /* ignore comments and empty lines */ if (strlen(line) == 0 || line[0] == '#') continue; /* Check for right groupname */ if (line[0] == '[') { if (group_found) { /* group info already read */ fclose(f); return 0; } if (strncmp(line + 1, service, strlen(service)) == 0 && line[strlen(service) + 1] == ']') group_found = true; else group_found = false; } else { if (group_found) { /* * Finally, we are in the right group and can parse * the line */ char *key, *val; bool found_keyword; key = line; val = strchr(line, '='); if (val == NULL) { printfPQExpBuffer(errorMessage, "ERROR: syntax error in service file '%s', line %d\n", serviceFile, linenr); fclose(f); return 3; } *val++ = '\0'; /* * Set the parameter --- but don't override any * previous explicit setting. */ found_keyword = false; for (i = 0; options[i].keyword; i++) { if (strcmp(options[i].keyword, key) == 0) { if (options[i].val == NULL) options[i].val = strdup(val); found_keyword = true; break; } } if (!found_keyword) { printfPQExpBuffer(errorMessage, "ERROR: syntax error in service file '%s', line %d\n", serviceFile, linenr); fclose(f); return 3; } } } } fclose(f); } return 0;}/* * Conninfo parser routine * * If successful, a malloc'd PQconninfoOption array is returned. * If not successful, NULL is returned and an error message is * left in errorMessage. */static PQconninfoOption *conninfo_parse(const char *conninfo, PQExpBuffer errorMessage){ char *pname; char *pval; char *buf; char *tmp; char *cp; char *cp2; PQconninfoOption *options; PQconninfoOption *option; char errortmp[PQERRORMSG_LENGTH]; /* Make a working copy of PQconninfoOptions */ options = malloc(sizeof(PQconninfoOptions)); if (options == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); return NULL; } memcpy(options, PQconninfoOptions, sizeof(PQconninfoOptions)); /* Need a modifiable copy of the input string */ if ((buf = strdup(conninfo)) == NULL) { printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n")); PQconninfoFree(options); return NULL; } cp = buf; while (*cp) { /* Skip blanks before the parameter name */ if (isspace((unsigned char) *cp)) { cp++; continue; } /* Get the parameter name */ pname = cp; while (*cp) { if (*cp == '=') break; if (isspace((unsigned char) *cp)) { *cp++ = '\0'; while (*cp) { if (!isspace((unsigned char) *cp)) break; cp++; } break; } cp++; } /* Check that there is a following '=' */ if (*cp != '=') { printfPQExpBuffer(errorMessage, libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"), pname); PQconninfoFree(options); free(buf); return NULL; } *cp++ = '\0'; /* Skip blanks after the '=' */ while (*cp) { if (!isspace((unsigned char) *cp)) break; cp++; } /* Get the parameter value */ pval = cp; if (*cp != '\'') { cp2 = pval; while (*cp) { if (isspace((unsigned char) *cp)) { *cp++ = '\0'; break; } if (*cp == '\\') { cp++; if (*cp != '\0') *cp2++ = *cp++; } else *cp2++ = *cp++; } *cp2 = '\0'; } else { cp2 = pval; cp++; for (;;) { if (*cp == '\0') { printfPQExpBuffer(errorMessage, libpq_gettext("unterminated quoted string in connection info string\n")); PQconninfoFree(options); free(buf); return NULL; } if (*cp == '\\') { cp++; if (*cp != '\0') *cp2++ = *cp++; continue; } if (*cp == '\'') { *cp2 = '\0'; cp++; break; } *cp2++ = *cp++; } } /* * Now we have the name and the value. Search for the param * record. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?