00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "postgres_fe.h"
00032
00033 #include <signal.h>
00034 #include <time.h>
00035
00036 #include <netinet/in.h>
00037 #include <arpa/inet.h>
00038
00039 #ifdef WIN32
00040 #include "win32.h"
00041 #else
00042 #include <unistd.h>
00043 #include <sys/time.h>
00044 #endif
00045
00046 #ifdef HAVE_POLL_H
00047 #include <poll.h>
00048 #endif
00049 #ifdef HAVE_SYS_POLL_H
00050 #include <sys/poll.h>
00051 #endif
00052 #ifdef HAVE_SYS_SELECT_H
00053 #include <sys/select.h>
00054 #endif
00055
00056 #include "libpq-fe.h"
00057 #include "libpq-int.h"
00058 #include "mb/pg_wchar.h"
00059 #include "pg_config_paths.h"
00060
00061
00062 static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
00063 static int pqSendSome(PGconn *conn, int len);
00064 static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
00065 time_t end_time);
00066 static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
00067
00068
00069
00070
00071 int
00072 PQlibVersion(void)
00073 {
00074 return PG_VERSION_NUM;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 static void
00084 fputnbytes(FILE *f, const char *str, size_t n)
00085 {
00086 while (n-- > 0)
00087 fputc(*str++, f);
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 int
00099 pqGetc(char *result, PGconn *conn)
00100 {
00101 if (conn->inCursor >= conn->inEnd)
00102 return EOF;
00103
00104 *result = conn->inBuffer[conn->inCursor++];
00105
00106 if (conn->Pfdebug)
00107 fprintf(conn->Pfdebug, "From backend> %c\n", *result);
00108
00109 return 0;
00110 }
00111
00112
00113
00114
00115
00116 int
00117 pqPutc(char c, PGconn *conn)
00118 {
00119 if (pqPutMsgBytes(&c, 1, conn))
00120 return EOF;
00121
00122 if (conn->Pfdebug)
00123 fprintf(conn->Pfdebug, "To backend> %c\n", c);
00124
00125 return 0;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 static int
00137 pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
00138 {
00139
00140 char *inBuffer = conn->inBuffer;
00141 int inCursor = conn->inCursor;
00142 int inEnd = conn->inEnd;
00143 int slen;
00144
00145 while (inCursor < inEnd && inBuffer[inCursor])
00146 inCursor++;
00147
00148 if (inCursor >= inEnd)
00149 return EOF;
00150
00151 slen = inCursor - conn->inCursor;
00152
00153 if (resetbuffer)
00154 resetPQExpBuffer(buf);
00155
00156 appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
00157
00158 conn->inCursor = ++inCursor;
00159
00160 if (conn->Pfdebug)
00161 fprintf(conn->Pfdebug, "From backend> \"%s\"\n",
00162 buf->data);
00163
00164 return 0;
00165 }
00166
00167 int
00168 pqGets(PQExpBuffer buf, PGconn *conn)
00169 {
00170 return pqGets_internal(buf, conn, true);
00171 }
00172
00173 int
00174 pqGets_append(PQExpBuffer buf, PGconn *conn)
00175 {
00176 return pqGets_internal(buf, conn, false);
00177 }
00178
00179
00180
00181
00182
00183 int
00184 pqPuts(const char *s, PGconn *conn)
00185 {
00186 if (pqPutMsgBytes(s, strlen(s) + 1, conn))
00187 return EOF;
00188
00189 if (conn->Pfdebug)
00190 fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
00191
00192 return 0;
00193 }
00194
00195
00196
00197
00198
00199 int
00200 pqGetnchar(char *s, size_t len, PGconn *conn)
00201 {
00202 if (len > (size_t) (conn->inEnd - conn->inCursor))
00203 return EOF;
00204
00205 memcpy(s, conn->inBuffer + conn->inCursor, len);
00206
00207
00208 conn->inCursor += len;
00209
00210 if (conn->Pfdebug)
00211 {
00212 fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
00213 fputnbytes(conn->Pfdebug, s, len);
00214 fprintf(conn->Pfdebug, "\n");
00215 }
00216
00217 return 0;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 int
00229 pqSkipnchar(size_t len, PGconn *conn)
00230 {
00231 if (len > (size_t) (conn->inEnd - conn->inCursor))
00232 return EOF;
00233
00234 if (conn->Pfdebug)
00235 {
00236 fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
00237 fputnbytes(conn->Pfdebug, conn->inBuffer + conn->inCursor, len);
00238 fprintf(conn->Pfdebug, "\n");
00239 }
00240
00241 conn->inCursor += len;
00242
00243 return 0;
00244 }
00245
00246
00247
00248
00249
00250 int
00251 pqPutnchar(const char *s, size_t len, PGconn *conn)
00252 {
00253 if (pqPutMsgBytes(s, len, conn))
00254 return EOF;
00255
00256 if (conn->Pfdebug)
00257 {
00258 fprintf(conn->Pfdebug, "To backend> ");
00259 fputnbytes(conn->Pfdebug, s, len);
00260 fprintf(conn->Pfdebug, "\n");
00261 }
00262
00263 return 0;
00264 }
00265
00266
00267
00268
00269
00270
00271 int
00272 pqGetInt(int *result, size_t bytes, PGconn *conn)
00273 {
00274 uint16 tmp2;
00275 uint32 tmp4;
00276
00277 switch (bytes)
00278 {
00279 case 2:
00280 if (conn->inCursor + 2 > conn->inEnd)
00281 return EOF;
00282 memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
00283 conn->inCursor += 2;
00284 *result = (int) ntohs(tmp2);
00285 break;
00286 case 4:
00287 if (conn->inCursor + 4 > conn->inEnd)
00288 return EOF;
00289 memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
00290 conn->inCursor += 4;
00291 *result = (int) ntohl(tmp4);
00292 break;
00293 default:
00294 pqInternalNotice(&conn->noticeHooks,
00295 "integer of size %lu not supported by pqGetInt",
00296 (unsigned long) bytes);
00297 return EOF;
00298 }
00299
00300 if (conn->Pfdebug)
00301 fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
00302
00303 return 0;
00304 }
00305
00306
00307
00308
00309
00310
00311 int
00312 pqPutInt(int value, size_t bytes, PGconn *conn)
00313 {
00314 uint16 tmp2;
00315 uint32 tmp4;
00316
00317 switch (bytes)
00318 {
00319 case 2:
00320 tmp2 = htons((uint16) value);
00321 if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
00322 return EOF;
00323 break;
00324 case 4:
00325 tmp4 = htonl((uint32) value);
00326 if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
00327 return EOF;
00328 break;
00329 default:
00330 pqInternalNotice(&conn->noticeHooks,
00331 "integer of size %lu not supported by pqPutInt",
00332 (unsigned long) bytes);
00333 return EOF;
00334 }
00335
00336 if (conn->Pfdebug)
00337 fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
00338
00339 return 0;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 int
00349 pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
00350 {
00351 int newsize = conn->outBufSize;
00352 char *newbuf;
00353
00354 if (bytes_needed <= (size_t) newsize)
00355 return 0;
00356
00357
00358
00359
00360
00361
00362
00363
00364 do
00365 {
00366 newsize *= 2;
00367 } while (newsize > 0 && bytes_needed > (size_t) newsize);
00368
00369 if (newsize > 0 && bytes_needed <= (size_t) newsize)
00370 {
00371 newbuf = realloc(conn->outBuffer, newsize);
00372 if (newbuf)
00373 {
00374
00375 conn->outBuffer = newbuf;
00376 conn->outBufSize = newsize;
00377 return 0;
00378 }
00379 }
00380
00381 newsize = conn->outBufSize;
00382 do
00383 {
00384 newsize += 8192;
00385 } while (newsize > 0 && bytes_needed > (size_t) newsize);
00386
00387 if (newsize > 0 && bytes_needed <= (size_t) newsize)
00388 {
00389 newbuf = realloc(conn->outBuffer, newsize);
00390 if (newbuf)
00391 {
00392
00393 conn->outBuffer = newbuf;
00394 conn->outBufSize = newsize;
00395 return 0;
00396 }
00397 }
00398
00399
00400 printfPQExpBuffer(&conn->errorMessage,
00401 "cannot allocate memory for output buffer\n");
00402 return EOF;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411 int
00412 pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
00413 {
00414 int newsize = conn->inBufSize;
00415 char *newbuf;
00416
00417 if (bytes_needed <= (size_t) newsize)
00418 return 0;
00419
00420
00421
00422
00423
00424
00425
00426
00427 do
00428 {
00429 newsize *= 2;
00430 } while (newsize > 0 && bytes_needed > (size_t) newsize);
00431
00432 if (newsize > 0 && bytes_needed <= (size_t) newsize)
00433 {
00434 newbuf = realloc(conn->inBuffer, newsize);
00435 if (newbuf)
00436 {
00437
00438 conn->inBuffer = newbuf;
00439 conn->inBufSize = newsize;
00440 return 0;
00441 }
00442 }
00443
00444 newsize = conn->inBufSize;
00445 do
00446 {
00447 newsize += 8192;
00448 } while (newsize > 0 && bytes_needed > (size_t) newsize);
00449
00450 if (newsize > 0 && bytes_needed <= (size_t) newsize)
00451 {
00452 newbuf = realloc(conn->inBuffer, newsize);
00453 if (newbuf)
00454 {
00455
00456 conn->inBuffer = newbuf;
00457 conn->inBufSize = newsize;
00458 return 0;
00459 }
00460 }
00461
00462
00463 printfPQExpBuffer(&conn->errorMessage,
00464 "cannot allocate memory for input buffer\n");
00465 return EOF;
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 int
00492 pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
00493 {
00494 int lenPos;
00495 int endPos;
00496
00497
00498 if (msg_type)
00499 endPos = conn->outCount + 1;
00500 else
00501 endPos = conn->outCount;
00502
00503
00504 if (force_len || PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
00505 {
00506 lenPos = endPos;
00507
00508 endPos += 4;
00509 }
00510 else
00511 lenPos = -1;
00512
00513
00514 if (pqCheckOutBufferSpace(endPos, conn))
00515 return EOF;
00516
00517 if (msg_type)
00518 conn->outBuffer[conn->outCount] = msg_type;
00519
00520 conn->outMsgStart = lenPos;
00521 conn->outMsgEnd = endPos;
00522
00523
00524 if (conn->Pfdebug)
00525 fprintf(conn->Pfdebug, "To backend> Msg %c\n",
00526 msg_type ? msg_type : ' ');
00527
00528 return 0;
00529 }
00530
00531
00532
00533
00534
00535
00536 static int
00537 pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
00538 {
00539
00540 if (pqCheckOutBufferSpace(conn->outMsgEnd + len, conn))
00541 return EOF;
00542
00543 memcpy(conn->outBuffer + conn->outMsgEnd, buf, len);
00544 conn->outMsgEnd += len;
00545
00546 return 0;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 int
00560 pqPutMsgEnd(PGconn *conn)
00561 {
00562 if (conn->Pfdebug)
00563 fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
00564 conn->outMsgEnd - conn->outCount);
00565
00566
00567 if (conn->outMsgStart >= 0)
00568 {
00569 uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
00570
00571 msgLen = htonl(msgLen);
00572 memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
00573 }
00574
00575
00576 conn->outCount = conn->outMsgEnd;
00577
00578 if (conn->outCount >= 8192)
00579 {
00580 int toSend = conn->outCount - (conn->outCount % 8192);
00581
00582 if (pqSendSome(conn, toSend) < 0)
00583 return EOF;
00584
00585 }
00586
00587 return 0;
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 int
00602 pqReadData(PGconn *conn)
00603 {
00604 int someread = 0;
00605 int nread;
00606
00607 if (conn->sock < 0)
00608 {
00609 printfPQExpBuffer(&conn->errorMessage,
00610 libpq_gettext("connection not open\n"));
00611 return -1;
00612 }
00613
00614
00615 if (conn->inStart < conn->inEnd)
00616 {
00617 if (conn->inStart > 0)
00618 {
00619 memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
00620 conn->inEnd - conn->inStart);
00621 conn->inEnd -= conn->inStart;
00622 conn->inCursor -= conn->inStart;
00623 conn->inStart = 0;
00624 }
00625 }
00626 else
00627 {
00628
00629 conn->inStart = conn->inCursor = conn->inEnd = 0;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 if (conn->inBufSize - conn->inEnd < 8192)
00641 {
00642 if (pqCheckInBufferSpace(conn->inEnd + (size_t) 8192, conn))
00643 {
00644
00645
00646
00647 if (conn->inBufSize - conn->inEnd < 100)
00648 return -1;
00649 }
00650 }
00651
00652
00653 retry3:
00654 nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
00655 conn->inBufSize - conn->inEnd);
00656 if (nread < 0)
00657 {
00658 if (SOCK_ERRNO == EINTR)
00659 goto retry3;
00660
00661 #ifdef EAGAIN
00662 if (SOCK_ERRNO == EAGAIN)
00663 return someread;
00664 #endif
00665 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
00666 if (SOCK_ERRNO == EWOULDBLOCK)
00667 return someread;
00668 #endif
00669
00670 #ifdef ECONNRESET
00671 if (SOCK_ERRNO == ECONNRESET)
00672 goto definitelyFailed;
00673 #endif
00674
00675 return -1;
00676 }
00677 if (nread > 0)
00678 {
00679 conn->inEnd += nread;
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 if (conn->inEnd > 32768 &&
00694 (conn->inBufSize - conn->inEnd) >= 8192)
00695 {
00696 someread = 1;
00697 goto retry3;
00698 }
00699 return 1;
00700 }
00701
00702 if (someread)
00703 return 1;
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 #ifdef USE_SSL
00721 if (conn->ssl)
00722 return 0;
00723 #endif
00724
00725 switch (pqReadReady(conn))
00726 {
00727 case 0:
00728
00729 return 0;
00730 case 1:
00731
00732 break;
00733 default:
00734 printfPQExpBuffer(&conn->errorMessage,
00735 libpq_gettext(
00736 "server closed the connection unexpectedly\n"
00737 "\tThis probably means the server terminated abnormally\n"
00738 "\tbefore or while processing the request.\n"));
00739 goto definitelyFailed;
00740 }
00741
00742
00743
00744
00745
00746 retry4:
00747 nread = pqsecure_read(conn, conn->inBuffer + conn->inEnd,
00748 conn->inBufSize - conn->inEnd);
00749 if (nread < 0)
00750 {
00751 if (SOCK_ERRNO == EINTR)
00752 goto retry4;
00753
00754 #ifdef EAGAIN
00755 if (SOCK_ERRNO == EAGAIN)
00756 return 0;
00757 #endif
00758 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
00759 if (SOCK_ERRNO == EWOULDBLOCK)
00760 return 0;
00761 #endif
00762
00763 #ifdef ECONNRESET
00764 if (SOCK_ERRNO == ECONNRESET)
00765 goto definitelyFailed;
00766 #endif
00767
00768 return -1;
00769 }
00770 if (nread > 0)
00771 {
00772 conn->inEnd += nread;
00773 return 1;
00774 }
00775
00776
00777
00778
00779
00780
00781 definitelyFailed:
00782 pqDropConnection(conn);
00783 conn->status = CONNECTION_BAD;
00784 return -1;
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 static int
00797 pqSendSome(PGconn *conn, int len)
00798 {
00799 char *ptr = conn->outBuffer;
00800 int remaining = conn->outCount;
00801 int result = 0;
00802
00803 if (conn->sock < 0)
00804 {
00805 printfPQExpBuffer(&conn->errorMessage,
00806 libpq_gettext("connection not open\n"));
00807 return -1;
00808 }
00809
00810
00811 while (len > 0)
00812 {
00813 int sent;
00814
00815 #ifndef WIN32
00816 sent = pqsecure_write(conn, ptr, len);
00817 #else
00818
00819
00820
00821
00822
00823
00824 sent = pqsecure_write(conn, ptr, Min(len, 65536));
00825 #endif
00826
00827 if (sent < 0)
00828 {
00829
00830 switch (SOCK_ERRNO)
00831 {
00832 #ifdef EAGAIN
00833 case EAGAIN:
00834 break;
00835 #endif
00836 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
00837 case EWOULDBLOCK:
00838 break;
00839 #endif
00840 case EINTR:
00841 continue;
00842
00843 default:
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 conn->outCount = 0;
00855 return -1;
00856 }
00857 }
00858 else
00859 {
00860 ptr += sent;
00861 len -= sent;
00862 remaining -= sent;
00863 }
00864
00865 if (len > 0)
00866 {
00867
00868
00869
00870
00871
00872
00873 if (pqIsnonblocking(conn))
00874 {
00875 result = 1;
00876 break;
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 if (pqReadData(conn) < 0)
00892 {
00893 result = -1;
00894 break;
00895 }
00896 if (pqWait(TRUE, TRUE, conn))
00897 {
00898 result = -1;
00899 break;
00900 }
00901 }
00902 }
00903
00904
00905 if (remaining > 0)
00906 memmove(conn->outBuffer, ptr, remaining);
00907 conn->outCount = remaining;
00908
00909 return result;
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919 int
00920 pqFlush(PGconn *conn)
00921 {
00922 if (conn->Pfdebug)
00923 fflush(conn->Pfdebug);
00924
00925 if (conn->outCount > 0)
00926 return pqSendSome(conn, conn->outCount);
00927
00928 return 0;
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942 int
00943 pqWait(int forRead, int forWrite, PGconn *conn)
00944 {
00945 return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 int
00958 pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
00959 {
00960 int result;
00961
00962 result = pqSocketCheck(conn, forRead, forWrite, finish_time);
00963
00964 if (result < 0)
00965 return EOF;
00966
00967 if (result == 0)
00968 {
00969 printfPQExpBuffer(&conn->errorMessage,
00970 libpq_gettext("timeout expired\n"));
00971 return EOF;
00972 }
00973
00974 return 0;
00975 }
00976
00977
00978
00979
00980
00981 int
00982 pqReadReady(PGconn *conn)
00983 {
00984 return pqSocketCheck(conn, 1, 0, (time_t) 0);
00985 }
00986
00987
00988
00989
00990
00991 int
00992 pqWriteReady(PGconn *conn)
00993 {
00994 return pqSocketCheck(conn, 0, 1, (time_t) 0);
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 static int
01006 pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
01007 {
01008 int result;
01009
01010 if (!conn)
01011 return -1;
01012 if (conn->sock < 0)
01013 {
01014 printfPQExpBuffer(&conn->errorMessage,
01015 libpq_gettext("socket not open\n"));
01016 return -1;
01017 }
01018
01019 #ifdef USE_SSL
01020
01021 if (forRead && conn->ssl && SSL_pending(conn->ssl) > 0)
01022 {
01023
01024 return 1;
01025 }
01026 #endif
01027
01028
01029 do
01030 result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);
01031 while (result < 0 && SOCK_ERRNO == EINTR);
01032
01033 if (result < 0)
01034 {
01035 char sebuf[256];
01036
01037 printfPQExpBuffer(&conn->errorMessage,
01038 libpq_gettext("select() failed: %s\n"),
01039 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
01040 }
01041
01042 return result;
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 static int
01056 pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
01057 {
01058
01059 #ifdef HAVE_POLL
01060 struct pollfd input_fd;
01061 int timeout_ms;
01062
01063 if (!forRead && !forWrite)
01064 return 0;
01065
01066 input_fd.fd = sock;
01067 input_fd.events = POLLERR;
01068 input_fd.revents = 0;
01069
01070 if (forRead)
01071 input_fd.events |= POLLIN;
01072 if (forWrite)
01073 input_fd.events |= POLLOUT;
01074
01075
01076 if (end_time == ((time_t) -1))
01077 timeout_ms = -1;
01078 else
01079 {
01080 time_t now = time(NULL);
01081
01082 if (end_time > now)
01083 timeout_ms = (end_time - now) * 1000;
01084 else
01085 timeout_ms = 0;
01086 }
01087
01088 return poll(&input_fd, 1, timeout_ms);
01089 #else
01090
01091 fd_set input_mask;
01092 fd_set output_mask;
01093 fd_set except_mask;
01094 struct timeval timeout;
01095 struct timeval *ptr_timeout;
01096
01097 if (!forRead && !forWrite)
01098 return 0;
01099
01100 FD_ZERO(&input_mask);
01101 FD_ZERO(&output_mask);
01102 FD_ZERO(&except_mask);
01103 if (forRead)
01104 FD_SET(sock, &input_mask);
01105
01106 if (forWrite)
01107 FD_SET(sock, &output_mask);
01108 FD_SET(sock, &except_mask);
01109
01110
01111 if (end_time == ((time_t) -1))
01112 ptr_timeout = NULL;
01113 else
01114 {
01115 time_t now = time(NULL);
01116
01117 if (end_time > now)
01118 timeout.tv_sec = end_time - now;
01119 else
01120 timeout.tv_sec = 0;
01121 timeout.tv_usec = 0;
01122 ptr_timeout = &timeout;
01123 }
01124
01125 return select(sock + 1, &input_mask, &output_mask,
01126 &except_mask, ptr_timeout);
01127 #endif
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 int
01141 PQmblen(const char *s, int encoding)
01142 {
01143 return pg_encoding_mblen(encoding, s);
01144 }
01145
01146
01147
01148
01149
01150 int
01151 PQdsplen(const char *s, int encoding)
01152 {
01153 return pg_encoding_dsplen(encoding, s);
01154 }
01155
01156
01157
01158
01159 int
01160 PQenv2encoding(void)
01161 {
01162 char *str;
01163 int encoding = PG_SQL_ASCII;
01164
01165 str = getenv("PGCLIENTENCODING");
01166 if (str && *str != '\0')
01167 {
01168 encoding = pg_char_to_encoding(str);
01169 if (encoding < 0)
01170 encoding = PG_SQL_ASCII;
01171 }
01172 return encoding;
01173 }
01174
01175
01176 #ifdef ENABLE_NLS
01177
01178 char *
01179 libpq_gettext(const char *msgid)
01180 {
01181 static bool already_bound = false;
01182
01183 if (!already_bound)
01184 {
01185
01186 #ifdef WIN32
01187 int save_errno = GetLastError();
01188 #else
01189 int save_errno = errno;
01190 #endif
01191 const char *ldir;
01192
01193 already_bound = true;
01194
01195 ldir = getenv("PGLOCALEDIR");
01196 if (!ldir)
01197 ldir = LOCALEDIR;
01198 bindtextdomain(PG_TEXTDOMAIN("libpq"), ldir);
01199 #ifdef WIN32
01200 SetLastError(save_errno);
01201 #else
01202 errno = save_errno;
01203 #endif
01204 }
01205
01206 return dgettext(PG_TEXTDOMAIN("libpq"), msgid);
01207 }
01208
01209 #endif