]> granicus.if.org Git - postgresql/blob - src/interfaces/libpq/fe-misc.c
Make pgsql compile on FreeBSD-alpha.
[postgresql] / src / interfaces / libpq / fe-misc.c
1 /*-------------------------------------------------------------------------
2  *
3  *       FILE
4  *              fe-misc.c
5  *
6  *       DESCRIPTION
7  *               miscellaneous useful functions
8  *
9  * The communication routines here are analogous to the ones in
10  * backend/libpq/pqcomm.c and backend/libpq/pqcomprim.c, but operate
11  * in the considerably different environment of the frontend libpq.
12  * In particular, we work with a bare nonblock-mode socket, rather than
13  * a stdio stream, so that we can avoid unwanted blocking of the application.
14  *
15  * XXX: MOVE DEBUG PRINTOUT TO HIGHER LEVEL.  As is, block and restart
16  * will cause repeat printouts.
17  *
18  * We must speak the same transmitted data representations as the backend
19  * routines.  Note that this module supports *only* network byte order
20  * for transmitted ints, whereas the backend modules (as of this writing)
21  * still handle either network or little-endian byte order.
22  *
23  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
24  * Portions Copyright (c) 1994, Regents of the University of California
25  *
26  *
27  * IDENTIFICATION
28  *        $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.42 2000/11/16 05:51:05 momjian Exp $
29  *
30  *-------------------------------------------------------------------------
31  */
32
33 #include "postgres.h"
34
35 #ifdef WIN32
36 #include "win32.h"
37 #else
38 #include <unistd.h>
39 #include <sys/time.h>
40 #endif
41
42 #include <errno.h>
43 #include <signal.h>
44 #include <time.h>
45
46 #ifdef HAVE_SYS_SELECT_H
47 #include <sys/select.h>
48 #endif
49
50 #include "libpq-fe.h"
51 #include "libpq-int.h"
52 #include "pqsignal.h"
53
54 #ifdef MULTIBYTE
55 #include "miscadmin.h"
56 #include "mb/pg_wchar.h"
57 #endif
58
59
60 #define DONOTICE(conn,message) \
61         ((*(conn)->noticeHook) ((conn)->noticeArg, (message)))
62
63
64 /* --------------------------------------------------------------------- */
65 /* pqGetc:
66    get a character from the connection
67
68    All these routines return 0 on success, EOF on error.
69    Note that for the Get routines, EOF only means there is not enough
70    data in the buffer, not that there is necessarily a hard error.
71 */
72 int
73 pqGetc(char *result, PGconn *conn)
74 {
75         if (conn->inCursor >= conn->inEnd)
76                 return EOF;
77
78         *result = conn->inBuffer[conn->inCursor++];
79
80         if (conn->Pfdebug)
81                 fprintf(conn->Pfdebug, "From backend> %c\n", *result);
82
83         return 0;
84 }
85
86
87 /* --------------------------------------------------------------------- */
88 /* pqPutBytes: local routine to write N bytes to the connection,
89    with buffering
90  */
91 static int
92 pqPutBytes(const char *s, size_t nbytes, PGconn *conn)
93 {
94         size_t          avail = Max(conn->outBufSize - conn->outCount, 0);
95
96         /*
97          * if we are non-blocking and the send queue is too full to buffer
98          * this request then try to flush some and return an error
99          */
100         if (pqIsnonblocking(conn) && nbytes > avail && pqFlush(conn))
101         {
102
103                 /*
104                  * even if the flush failed we may still have written some data,
105                  * recalculate the size of the send-queue relative to the amount
106                  * we have to send, we may be able to queue it afterall even
107                  * though it's not sent to the database it's ok, any routines that
108                  * check the data coming from the database better call pqFlush()
109                  * anyway.
110                  */
111                 if (nbytes > Max(conn->outBufSize - conn->outCount, 0))
112                 {
113                         printfPQExpBuffer(&conn->errorMessage,
114                                                    "pqPutBytes --  pqFlush couldn't flush enough"
115                                                  " data: space available: %d, space needed %d\n",
116                                           Max(conn->outBufSize - conn->outCount, 0), nbytes);
117                         return EOF;
118                 }
119                 /* fixup avail for while loop */
120                 avail = Max(conn->outBufSize - conn->outCount, 0);
121         }
122
123         /*
124          * is the amount of data to be sent is larger than the size of the
125          * output buffer then we must flush it to make more room.
126          *
127          * the code above will make sure the loop conditional is never true for
128          * non-blocking connections
129          */
130         while (nbytes > avail)
131         {
132                 memcpy(conn->outBuffer + conn->outCount, s, avail);
133                 conn->outCount += avail;
134                 s += avail;
135                 nbytes -= avail;
136                 if (pqFlush(conn))
137                         return EOF;
138                 avail = conn->outBufSize;
139         }
140
141         memcpy(conn->outBuffer + conn->outCount, s, nbytes);
142         conn->outCount += nbytes;
143
144         return 0;
145 }
146
147 /* --------------------------------------------------------------------- */
148 /* pqGets:
149    get a null-terminated string from the connection,
150    and store it in an expansible PQExpBuffer.
151    If we run out of memory, all of the string is still read,
152    but the excess characters are silently discarded.
153 */
154 int
155 pqGets(PQExpBuffer buf, PGconn *conn)
156 {
157         /* Copy conn data to locals for faster search loop */
158         char       *inBuffer = conn->inBuffer;
159         int                     inCursor = conn->inCursor;
160         int                     inEnd = conn->inEnd;
161         int                     slen;
162
163         while (inCursor < inEnd && inBuffer[inCursor])
164                 inCursor++;
165
166         if (inCursor >= inEnd)
167                 return EOF;
168
169         slen = inCursor - conn->inCursor;
170
171         resetPQExpBuffer(buf);
172         appendBinaryPQExpBuffer(buf, inBuffer + conn->inCursor, slen);
173
174         conn->inCursor = ++inCursor;
175
176         if (conn->Pfdebug)
177                 fprintf(conn->Pfdebug, "From backend> \"%s\"\n",
178                                 buf->data);
179
180         return 0;
181 }
182
183 /* --------------------------------------------------------------------- */
184 int
185 pqPuts(const char *s, PGconn *conn)
186 {
187         if (pqPutBytes(s, strlen(s) + 1, conn))
188                 return EOF;
189
190         if (conn->Pfdebug)
191                 fprintf(conn->Pfdebug, "To backend> %s\n", s);
192
193         return 0;
194 }
195
196 /* --------------------------------------------------------------------- */
197 /* pqGetnchar:
198    get a string of exactly len bytes in buffer s, no null termination
199 */
200 int
201 pqGetnchar(char *s, size_t len, PGconn *conn)
202 {
203         if (len < 0 || len > conn->inEnd - conn->inCursor)
204                 return EOF;
205
206         memcpy(s, conn->inBuffer + conn->inCursor, len);
207         /* no terminating null */
208
209         conn->inCursor += len;
210
211         if (conn->Pfdebug)
212                 fprintf(conn->Pfdebug, "From backend (%lu)> %.*s\n", (unsigned long)len, (int) len, s);
213
214         return 0;
215 }
216
217 /* --------------------------------------------------------------------- */
218 /* pqPutnchar:
219    send a string of exactly len bytes, no null termination needed
220 */
221 int
222 pqPutnchar(const char *s, size_t len, PGconn *conn)
223 {
224         if (pqPutBytes(s, len, conn))
225                 return EOF;
226
227         if (conn->Pfdebug)
228                 fprintf(conn->Pfdebug, "To backend> %.*s\n", (int) len, s);
229
230         return 0;
231 }
232
233 /* --------------------------------------------------------------------- */
234 /* pgGetInt
235    read a 2 or 4 byte integer and convert from network byte order
236    to local byte order
237 */
238 int
239 pqGetInt(int *result, size_t bytes, PGconn *conn)
240 {
241         uint16          tmp2;
242         uint32          tmp4;
243         char            noticeBuf[64];
244
245         switch (bytes)
246         {
247                 case 2:
248                         if (conn->inCursor + 2 > conn->inEnd)
249                                 return EOF;
250                         memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2);
251                         conn->inCursor += 2;
252                         *result = (int) ntohs(tmp2);
253                         break;
254                 case 4:
255                         if (conn->inCursor + 4 > conn->inEnd)
256                                 return EOF;
257                         memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4);
258                         conn->inCursor += 4;
259                         *result = (int) ntohl(tmp4);
260                         break;
261                 default:
262                         sprintf(noticeBuf,
263                                         "pqGetInt: int size %lu not supported\n", (unsigned long)bytes);
264                         DONOTICE(conn, noticeBuf);
265                         return EOF;
266         }
267
268         if (conn->Pfdebug)
269                 fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long)bytes, *result);
270
271         return 0;
272 }
273
274 /* --------------------------------------------------------------------- */
275 /* pgPutInt
276    send an integer of 2 or 4 bytes, converting from host byte order
277    to network byte order.
278 */
279 int
280 pqPutInt(int value, size_t bytes, PGconn *conn)
281 {
282         uint16          tmp2;
283         uint32          tmp4;
284         char            noticeBuf[64];
285
286         switch (bytes)
287         {
288                 case 2:
289                         tmp2 = htons((uint16) value);
290                         if (pqPutBytes((const char *) &tmp2, 2, conn))
291                                 return EOF;
292                         break;
293                 case 4:
294                         tmp4 = htonl((uint32) value);
295                         if (pqPutBytes((const char *) &tmp4, 4, conn))
296                                 return EOF;
297                         break;
298                 default:
299                         sprintf(noticeBuf,
300                                         "pqPutInt: int size %lu not supported\n", (unsigned long)bytes);
301                         DONOTICE(conn, noticeBuf);
302                         return EOF;
303         }
304
305         if (conn->Pfdebug)
306                 fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long)bytes, value);
307
308         return 0;
309 }
310
311 /* --------------------------------------------------------------------- */
312 /* pqReadReady: is select() saying the file is ready to read?
313  * Returns -1 on failure, 0 if not ready, 1 if ready.
314  */
315 int
316 pqReadReady(PGconn *conn)
317 {
318         fd_set          input_mask;
319         struct timeval timeout;
320
321         if (!conn || conn->sock < 0)
322                 return -1;
323
324         FD_ZERO(&input_mask);
325         FD_SET(conn->sock, &input_mask);
326         timeout.tv_sec = 0;
327         timeout.tv_usec = 0;
328 retry:
329         if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL,
330                            &timeout) < 0)
331         {
332                 if (errno == EINTR)
333                         /* Interrupted system call - we'll just try again */
334                         goto retry;
335
336                 printfPQExpBuffer(&conn->errorMessage,
337                                           "pqReadReady() -- select() failed: errno=%d\n%s\n",
338                                                   errno, strerror(errno));
339                 return -1;
340         }
341
342         return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
343 }
344
345 /* --------------------------------------------------------------------- */
346 /* pqWriteReady: is select() saying the file is ready to write?
347  * Returns -1 on failure, 0 if not ready, 1 if ready.
348  */
349 int
350 pqWriteReady(PGconn *conn)
351 {
352         fd_set          input_mask;
353         struct timeval timeout;
354
355         if (!conn || conn->sock < 0)
356                 return -1;
357
358         FD_ZERO(&input_mask);
359         FD_SET(conn->sock, &input_mask);
360         timeout.tv_sec = 0;
361         timeout.tv_usec = 0;
362 retry:
363         if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL,
364                            &timeout) < 0)
365         {
366                 if (errno == EINTR)
367                         /* Interrupted system call - we'll just try again */
368                         goto retry;
369
370                 printfPQExpBuffer(&conn->errorMessage,
371                                          "pqWriteReady() -- select() failed: errno=%d\n%s\n",
372                                                   errno, strerror(errno));
373                 return -1;
374         }
375         return FD_ISSET(conn->sock, &input_mask) ? 1 : 0;
376 }
377
378 /* --------------------------------------------------------------------- */
379 /* pqReadData: read more data, if any is available
380  * Possible return values:
381  *       1: successfully loaded at least one more byte
382  *       0: no data is presently available, but no error detected
383  *      -1: error detected (including EOF = connection closure);
384  *              conn->errorMessage set
385  * NOTE: callers must not assume that pointers or indexes into conn->inBuffer
386  * remain valid across this call!
387  */
388 int
389 pqReadData(PGconn *conn)
390 {
391         int                     someread = 0;
392         int                     nread;
393
394         if (conn->sock < 0)
395         {
396                 printfPQExpBuffer(&conn->errorMessage,
397                                                   "pqReadData() -- connection not open\n");
398                 return -1;
399         }
400
401         /* Left-justify any data in the buffer to make room */
402         if (conn->inStart < conn->inEnd)
403         {
404                 memmove(conn->inBuffer, conn->inBuffer + conn->inStart,
405                                 conn->inEnd - conn->inStart);
406                 conn->inEnd -= conn->inStart;
407                 conn->inCursor -= conn->inStart;
408                 conn->inStart = 0;
409         }
410         else
411                 conn->inStart = conn->inCursor = conn->inEnd = 0;
412
413         /*
414          * If the buffer is fairly full, enlarge it. We need to be able to
415          * enlarge the buffer in case a single message exceeds the initial
416          * buffer size.  We enlarge before filling the buffer entirely so as
417          * to avoid asking the kernel for a partial packet. The magic constant
418          * here should be large enough for a TCP packet or Unix pipe
419          * bufferload.  8K is the usual pipe buffer size, so...
420          */
421         if (conn->inBufSize - conn->inEnd < 8192)
422         {
423                 int                     newSize = conn->inBufSize * 2;
424                 char       *newBuf = (char *) realloc(conn->inBuffer, newSize);
425
426                 if (newBuf)
427                 {
428                         conn->inBuffer = newBuf;
429                         conn->inBufSize = newSize;
430                 }
431         }
432
433         /* OK, try to read some data */
434 tryAgain:
435 #ifdef USE_SSL
436         if (conn->ssl)
437                 nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd,
438                                                  conn->inBufSize - conn->inEnd);
439         else
440 #endif
441                 nread = recv(conn->sock, conn->inBuffer + conn->inEnd,
442                                          conn->inBufSize - conn->inEnd, 0);
443         if (nread < 0)
444         {
445                 if (errno == EINTR)
446                         goto tryAgain;
447                 /* Some systems return EAGAIN/EWOULDBLOCK for no data */
448 #ifdef EAGAIN
449                 if (errno == EAGAIN)
450                         return someread;
451 #endif
452 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
453                 if (errno == EWOULDBLOCK)
454                         return someread;
455 #endif
456                 /* We might get ECONNRESET here if using TCP and backend died */
457 #ifdef ECONNRESET
458                 if (errno == ECONNRESET)
459                         goto definitelyFailed;
460 #endif
461                 printfPQExpBuffer(&conn->errorMessage,
462                                                 "pqReadData() --  read() failed: errno=%d\n%s\n",
463                                                   errno, strerror(errno));
464                 return -1;
465         }
466         if (nread > 0)
467         {
468                 conn->inEnd += nread;
469
470                 /*
471                  * Hack to deal with the fact that some kernels will only give us
472                  * back 1 packet per recv() call, even if we asked for more and
473                  * there is more available.  If it looks like we are reading a
474                  * long message, loop back to recv() again immediately, until we
475                  * run out of data or buffer space.  Without this, the
476                  * block-and-restart behavior of libpq's higher levels leads to
477                  * O(N^2) performance on long messages.
478                  *
479                  * Since we left-justified the data above, conn->inEnd gives the
480                  * amount of data already read in the current message.  We
481                  * consider the message "long" once we have acquired 32k ...
482                  */
483                 if (conn->inEnd > 32768 &&
484                         (conn->inBufSize - conn->inEnd) >= 8192)
485                 {
486                         someread = 1;
487                         goto tryAgain;
488                 }
489                 return 1;
490         }
491
492         if (someread)
493                 return 1;                               /* got a zero read after successful tries */
494
495         /*
496          * A return value of 0 could mean just that no data is now available,
497          * or it could mean EOF --- that is, the server has closed the
498          * connection. Since we have the socket in nonblock mode, the only way
499          * to tell the difference is to see if select() is saying that the
500          * file is ready. Grumble.      Fortunately, we don't expect this path to
501          * be taken much, since in normal practice we should not be trying to
502          * read data unless the file selected for reading already.
503          */
504         switch (pqReadReady(conn))
505         {
506                 case 0:
507                         /* definitely no data available */
508                         return 0;
509                 case 1:
510                         /* ready for read */
511                         break;
512                 default:
513                         goto definitelyFailed;
514         }
515
516         /*
517          * Still not sure that it's EOF, because some data could have just
518          * arrived.
519          */
520 tryAgain2:
521 #ifdef USE_SSL
522         if (conn->ssl)
523                 nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd,
524                                                  conn->inBufSize - conn->inEnd);
525         else
526 #endif
527                 nread = recv(conn->sock, conn->inBuffer + conn->inEnd,
528                                          conn->inBufSize - conn->inEnd, 0);
529         if (nread < 0)
530         {
531                 if (errno == EINTR)
532                         goto tryAgain2;
533                 /* Some systems return EAGAIN/EWOULDBLOCK for no data */
534 #ifdef EAGAIN
535                 if (errno == EAGAIN)
536                         return 0;
537 #endif
538 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
539                 if (errno == EWOULDBLOCK)
540                         return 0;
541 #endif
542                 /* We might get ECONNRESET here if using TCP and backend died */
543 #ifdef ECONNRESET
544                 if (errno == ECONNRESET)
545                         goto definitelyFailed;
546 #endif
547                 printfPQExpBuffer(&conn->errorMessage,
548                                                 "pqReadData() --  read() failed: errno=%d\n%s\n",
549                                                   errno, strerror(errno));
550                 return -1;
551         }
552         if (nread > 0)
553         {
554                 conn->inEnd += nread;
555                 return 1;
556         }
557
558         /*
559          * OK, we are getting a zero read even though select() says ready.
560          * This means the connection has been closed.  Cope.
561          */
562 definitelyFailed:
563         printfPQExpBuffer(&conn->errorMessage,
564                          "pqReadData() -- backend closed the channel unexpectedly.\n"
565                           "\tThis probably means the backend terminated abnormally\n"
566                                           "\tbefore or while processing the request.\n");
567         conn->status = CONNECTION_BAD;          /* No more connection to backend */
568 #ifdef WIN32
569         closesocket(conn->sock);
570 #else
571         close(conn->sock);
572 #endif
573         conn->sock = -1;
574
575         return -1;
576 }
577
578 /* --------------------------------------------------------------------- */
579 /* pqFlush: send any data waiting in the output buffer
580  */
581 int
582 pqFlush(PGconn *conn)
583 {
584         char       *ptr = conn->outBuffer;
585         int                     len = conn->outCount;
586
587         if (conn->sock < 0)
588         {
589                 printfPQExpBuffer(&conn->errorMessage,
590                                                   "pqFlush() -- connection not open\n");
591                 return EOF;
592         }
593
594         /*
595          * don't try to send zero data, allows us to use this function without
596          * too much worry about overhead
597          */
598         if (len == 0)
599                 return (0);
600
601         /* while there's still data to send */
602         while (len > 0)
603         {
604                 /* Prevent being SIGPIPEd if backend has closed the connection. */
605 #ifndef WIN32
606                 pqsigfunc       oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
607
608 #endif
609
610                 int                     sent;
611
612 #ifdef USE_SSL
613                 if (conn->ssl)
614                         sent = SSL_write(conn->ssl, ptr, len);
615                 else
616 #endif
617                         sent = send(conn->sock, ptr, len, 0);
618
619 #ifndef WIN32
620                 pqsignal(SIGPIPE, oldsighandler);
621 #endif
622
623                 if (sent < 0)
624                 {
625
626                         /*
627                          * Anything except EAGAIN or EWOULDBLOCK is trouble. If it's
628                          * EPIPE or ECONNRESET, assume we've lost the backend
629                          * connection permanently.
630                          */
631                         switch (errno)
632                         {
633 #ifdef EAGAIN
634                                 case EAGAIN:
635                                         break;
636 #endif
637 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
638                                 case EWOULDBLOCK:
639                                         break;
640 #endif
641                                 case EINTR:
642                                         continue;
643
644                                 case EPIPE:
645 #ifdef ECONNRESET
646                                 case ECONNRESET:
647 #endif
648                                         printfPQExpBuffer(&conn->errorMessage,
649                                                                           "pqFlush() -- backend closed the channel unexpectedly.\n"
650                                                                           "\tThis probably means the backend terminated abnormally"
651                                                    " before or while processing the request.\n");
652
653                                         /*
654                                          * We used to close the socket here, but that's a bad
655                                          * idea since there might be unread data waiting
656                                          * (typically, a NOTICE message from the backend
657                                          * telling us it's committing hara-kiri...).  Leave
658                                          * the socket open until pqReadData finds no more data
659                                          * can be read.
660                                          */
661                                         return EOF;
662
663                                 default:
664                                         printfPQExpBuffer(&conn->errorMessage,
665                                           "pqFlush() --  couldn't send data: errno=%d\n%s\n",
666                                                                           errno, strerror(errno));
667                                         /* We don't assume it's a fatal error... */
668                                         return EOF;
669                         }
670                 }
671                 else
672                 {
673                         ptr += sent;
674                         len -= sent;
675                 }
676
677                 if (len > 0)
678                 {
679                         /* We didn't send it all, wait till we can send more */
680
681                         /*
682                          * if the socket is in non-blocking mode we may need to abort
683                          * here
684                          */
685 #ifdef USE_SSL
686                         /* can't do anything for our SSL users yet */
687                         if (conn->ssl == NULL)
688                         {
689 #endif
690                                 if (pqIsnonblocking(conn))
691                                 {
692                                         /* shift the contents of the buffer */
693                                         memmove(conn->outBuffer, ptr, len);
694                                         conn->outCount = len;
695                                         return EOF;
696                                 }
697 #ifdef USE_SSL
698                         }
699 #endif
700
701                         if (pqWait(FALSE, TRUE, conn))
702                                 return EOF;
703                 }
704         }
705
706         conn->outCount = 0;
707
708         if (conn->Pfdebug)
709                 fflush(conn->Pfdebug);
710
711         return 0;
712 }
713
714 /* --------------------------------------------------------------------- */
715 /* pqWait: wait until we can read or write the connection socket
716  */
717 int
718 pqWait(int forRead, int forWrite, PGconn *conn)
719 {
720         fd_set          input_mask;
721         fd_set          output_mask;
722
723         if (conn->sock < 0)
724         {
725                 printfPQExpBuffer(&conn->errorMessage,
726                                                   "pqWait() -- connection not open\n");
727                 return EOF;
728         }
729
730         if (forRead || forWrite)
731         {
732 retry:
733                 FD_ZERO(&input_mask);
734                 FD_ZERO(&output_mask);
735                 if (forRead)
736                         FD_SET(conn->sock, &input_mask);
737                 if (forWrite)
738                         FD_SET(conn->sock, &output_mask);
739                 if (select(conn->sock + 1, &input_mask, &output_mask, (fd_set *) NULL,
740                                    (struct timeval *) NULL) < 0)
741                 {
742                         if (errno == EINTR)
743                                 goto retry;
744                         printfPQExpBuffer(&conn->errorMessage,
745                                                    "pqWait() -- select() failed: errno=%d\n%s\n",
746                                                           errno, strerror(errno));
747                         return EOF;
748                 }
749         }
750
751         return 0;
752 }
753
754
755
756 /*
757  * A couple of "miscellaneous" multibyte related functions. They used
758  * to be in fe-print.c but that file is doomed.
759  */
760
761 #ifdef MULTIBYTE
762 /*
763  * returns the byte length of the word beginning s, using the
764  * specified encoding.
765  */
766 int
767 PQmblen(const unsigned char *s, int encoding)
768 {
769         return (pg_encoding_mblen(encoding, s));
770 }
771
772 /*
773  * Get encoding id from environment variable PGCLIENTENCODING.
774  */
775 int
776 PQenv2encoding(void)
777 {
778         char       *str;
779         int                     encoding = SQL_ASCII;
780
781         str = getenv("PGCLIENTENCODING");
782         if (str && *str != '\0')
783                 encoding = pg_char_to_encoding(str);
784         return (encoding);
785 }
786
787 #else
788
789 /* Provide a default definition in case someone calls it anyway */
790 int
791 PQmblen(const unsigned char *s, int encoding)
792 {
793         (void) s;
794         (void) encoding;
795         return 1;
796 }
797 int
798 PQenv2encoding(void)
799 {
800         return 0;
801 }
802
803 #endif   /* MULTIBYTE */