client_login_timeout: check wait_for_welcome
[pgbouncer.git] / src / system.c
blob5867b7cf25fdf679069fc70c45a031c26b7b5b8d
1 /*
2 * PgBouncer - Lightweight connection pooler for PostgreSQL.
3 *
4 * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
5 *
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.
9 *
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.
23 #include "bouncer.h"
25 #ifdef HAVE_SYS_PARAM_H
26 #include <sys/param.h>
27 #endif
28 #ifdef HAVE_UCRED_H
29 #include <ucred.h>
30 #endif
31 #ifdef HAVE_SYS_UCRED_H
32 #include <sys/ucred.h>
33 #endif
34 #ifdef HAVE_PWD_H
35 #include <pwd.h>
36 #endif
37 #ifdef HAVE_GRP_H
38 #include <grp.h>
39 #endif
42 * Minimal spec-conforming implementations of strlcpy(), strlcat().
45 #ifndef HAVE_STRLCPY
46 size_t strlcpy(char *dst, const char *src, size_t n)
48 size_t len = strlen(src);
49 if (len < n) {
50 memcpy(dst, src, len + 1);
51 } else if (n > 0) {
52 memcpy(dst, src, n - 1);
53 dst[n - 1] = 0;
55 return len;
57 #endif
59 #ifndef HAVE_STRLCAT
60 size_t strlcat(char *dst, const char *src, size_t n)
62 size_t pos = 0;
63 while (pos < n && dst[pos])
64 pos++;
65 return pos + strlcpy(dst + pos, src, n - pos);
67 #endif
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)
77 #ifdef SO_PEERCRED
78 struct ucred cred;
79 socklen_t len = sizeof(cred);
80 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
81 *uid_p = cred.uid;
82 *gid_p = cred.gid;
83 return 0;
85 #else /* !SO_PEERCRED */
86 #ifdef HAVE_GETPEERUCRED
87 ucred_t *cred = NULL;
88 if (getpeerucred(fd, &cred) >= 0) {
89 *uid_p = ucred_geteuid(cred);
90 *gid_p = ucred_getegid(cred);
91 ucred_free(cred);
92 if (*uid_p >= 0 && *gid_p >= 0)
93 return 0;
95 #endif /* HAVE_GETPEERUCRED */
96 #endif /* !SO_PEERCRED */
97 return -1;
99 #endif /* !HAVE_GETPEEREID */
101 #ifndef HAVE_BASENAME
102 const char *basename(const char *path)
104 const char *p;
105 if (path == NULL || path[0] == 0)
106 return ".";
107 if ((p = strrchr(path, '/')) != NULL)
108 return p[1] ? p + 1 : p;
109 return path;
111 #endif
113 void change_user(const char *user)
115 const struct passwd *pw;
116 gid_t gset[1];
118 /* check for a valid username */
119 pw = getpwnam(user);
120 if (pw == NULL)
121 fatal("could not find user '%s' to switch to", user);
123 gset[0] = pw->pw_gid;
124 if (getuid() == 0) {
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;
140 if (af != AF_INET)
141 return NULL;
142 snprintf(dst, cnt, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
143 return dst;
145 #endif