2 * PgBouncer - Lightweight connection pooler for PostgreSQL.
4 * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * Compat functions for OSes where libc does not provide them.
25 #ifdef HAVE_SYS_PARAM_H
26 #include <sys/param.h>
31 #ifdef HAVE_SYS_UCRED_H
32 #include <sys/ucred.h>
42 * Minimal spec-conforming implementations of strlcpy(), strlcat().
46 size_t strlcpy(char *dst
, const char *src
, size_t n
)
48 size_t len
= strlen(src
);
50 memcpy(dst
, src
, len
+ 1);
52 memcpy(dst
, src
, n
- 1);
60 size_t strlcat(char *dst
, const char *src
, size_t n
)
63 while (pos
< n
&& dst
[pos
])
65 return pos
+ strlcpy(dst
+ pos
, src
, n
- pos
);
70 * Get other side's uid for UNIX socket.
72 * Standardise on getpeereid() from BSDs.
74 #ifndef HAVE_GETPEEREID
75 int getpeereid(int fd
, uid_t
*uid_p
, gid_t
*gid_p
)
79 socklen_t len
= sizeof(cred
);
80 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &cred
, &len
) >= 0) {
85 #else /* !SO_PEERCRED */
86 #ifdef HAVE_GETPEERUCRED
88 if (getpeerucred(fd
, &cred
) >= 0) {
89 *uid_p
= ucred_geteuid(cred
);
90 *gid_p
= ucred_getegid(cred
);
92 if (*uid_p
>= 0 && *gid_p
>= 0)
95 #endif /* HAVE_GETPEERUCRED */
96 #endif /* !SO_PEERCRED */
99 #endif /* !HAVE_GETPEEREID */
101 #ifndef HAVE_BASENAME
102 const char *basename(const char *path
)
105 if (path
== NULL
|| path
[0] == 0)
107 if ((p
= strrchr(path
, '/')) != NULL
)
108 return p
[1] ? p
+ 1 : p
;
113 void change_user(const char *user
)
115 const struct passwd
*pw
;
118 /* check for a valid username */
121 fatal("could not find user '%s' to switch to", user
);
123 gset
[0] = pw
->pw_gid
;
125 if (setgroups(1, gset
) < 0)
126 fatal_perror("failed to reset groups");
129 if (setgid(pw
->pw_gid
) < 0 || setuid(pw
->pw_uid
) < 0)
130 fatal_perror("failed to assume identity of user '%s'", user
);
132 if (getuid() != pw
->pw_uid
|| geteuid() != pw
->pw_uid
)
133 fatal("setuid() failed to work");
136 #ifndef HAVE_INET_NTOP
137 const char *inet_ntop(int af
, const void *src
, char *dst
, socklen_t cnt
)
139 const unsigned char *p
= src
;
142 snprintf(dst
, cnt
, "%d.%d.%d.%d", p
[0], p
[1], p
[2], p
[3]);