]> code.delx.au - pulseaudio/blob - src/pulse/util.c
* fall back to prctl(PR_GET_NAME) in pa_get_binary_name() if readlink() fails
[pulseaudio] / src / pulse / util.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27 #include <errno.h>
28 #include <limits.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35
36 #ifdef HAVE_PWD_H
37 #include <pwd.h>
38 #endif
39
40 #ifdef HAVE_SYS_SOCKET_H
41 #include <sys/socket.h>
42 #endif
43
44 #ifdef HAVE_NETDB_H
45 #include <netdb.h>
46 #endif
47
48 #ifdef HAVE_WINDOWS_H
49 #include <windows.h>
50 #endif
51
52 #ifdef HAVE_SYS_PRCTL_H
53 #include <sys/prctl.h>
54 #endif
55
56 #include "../pulsecore/winsock.h"
57
58 #include <pulsecore/core-error.h>
59 #include <pulsecore/log.h>
60 #include <pulsecore/core-util.h>
61
62 #include "util.h"
63
64 #ifndef OS_IS_WIN32
65 #define PATH_SEP '/'
66 #else
67 #define PATH_SEP '\\'
68 #endif
69
70 char *pa_get_user_name(char *s, size_t l) {
71 char *p;
72 char buf[1024];
73
74 #ifdef HAVE_PWD_H
75 struct passwd pw, *r;
76 #endif
77
78 assert(s && l > 0);
79
80 if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
81 #ifdef HAVE_PWD_H
82
83 #ifdef HAVE_GETPWUID_R
84 if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
85 #else
86 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
87 * that do not support getpwuid_r. */
88 if ((r = getpwuid(getuid())) == NULL) {
89 #endif
90 snprintf(s, l, "%lu", (unsigned long) getuid());
91 return s;
92 }
93
94 p = r->pw_name;
95
96 #elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
97 DWORD size = sizeof(buf);
98
99 if (!GetUserName(buf, &size))
100 return NULL;
101
102 p = buf;
103
104 #else /* HAVE_PWD_H */
105 return NULL;
106 #endif /* HAVE_PWD_H */
107 }
108
109 return pa_strlcpy(s, p, l);
110 }
111
112 char *pa_get_host_name(char *s, size_t l) {
113 assert(s && l > 0);
114 if (gethostname(s, l) < 0) {
115 pa_log(__FILE__": gethostname(): %s", pa_cstrerror(errno));
116 return NULL;
117 }
118 s[l-1] = 0;
119 return s;
120 }
121
122 char *pa_get_home_dir(char *s, size_t l) {
123 char *e;
124
125 #ifdef HAVE_PWD_H
126 char buf[1024];
127 struct passwd pw, *r;
128 #endif
129
130 assert(s && l);
131
132 if ((e = getenv("HOME")))
133 return pa_strlcpy(s, e, l);
134
135 if ((e = getenv("USERPROFILE")))
136 return pa_strlcpy(s, e, l);
137
138 #ifdef HAVE_PWD_H
139 #ifdef HAVE_GETPWUID_R
140 if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
141 pa_log(__FILE__": getpwuid_r() failed");
142 #else
143 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
144 * that do not support getpwuid_r. */
145 if ((r = getpwuid(getuid())) == NULL) {
146 pa_log(__FILE__": getpwuid_r() failed");
147 #endif
148 return NULL;
149 }
150
151 return pa_strlcpy(s, r->pw_dir, l);
152 #else /* HAVE_PWD_H */
153 return NULL;
154 #endif
155 }
156
157 char *pa_get_binary_name(char *s, size_t l) {
158
159 assert(s);
160 assert(l);
161
162 #if defined(OS_IS_WIN32)
163 {
164 char path[PATH_MAX];
165
166 if (GetModuleFileName(NULL, path, PATH_MAX))
167 return pa_strlcpy(s, pa_path_get_filename(path), l);
168 }
169 #endif
170
171 #ifdef HAVE_READLINK
172 {
173 int i;
174 char path[PATH_MAX];
175 /* This works on Linux only */
176
177 if ((i = readlink("/proc/self/exe", path, sizeof(path)-1)) >= 0) {
178 path[i] = 0;
179 return pa_strlcpy(s, pa_path_get_filename(path), l);
180 }
181 }
182
183 #endif
184
185 #if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_NAME)
186 {
187
188 #ifndef TASK_COMM_LEN
189 /* Actually defined in linux/sched.h */
190 #define TASK_COMM_LEN 16
191 #endif
192
193 char tcomm[TASK_COMM_LEN+1];
194 memset(tcomm, 0, sizeof(tcomm));
195
196 /* This works on Linux only */
197 if (prctl(PR_GET_NAME, (unsigned long) tcomm, 0, 0, 0) == 0)
198 return pa_strlcpy(s, tcomm, l);
199
200 }
201 #endif
202
203 return NULL;
204 }
205
206 const char *pa_path_get_filename(const char *p) {
207 char *fn;
208
209 if ((fn = strrchr(p, PATH_SEP)))
210 return fn+1;
211
212 return (const char*) p;
213 }
214
215 char *pa_get_fqdn(char *s, size_t l) {
216 char hn[256];
217 #ifdef HAVE_GETADDRINFO
218 struct addrinfo *a, hints;
219 #endif
220
221 if (!pa_get_host_name(hn, sizeof(hn)))
222 return NULL;
223
224 #ifdef HAVE_GETADDRINFO
225 memset(&hints, 0, sizeof(hints));
226 hints.ai_family = AF_UNSPEC;
227 hints.ai_flags = AI_CANONNAME;
228
229 if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname)
230 return pa_strlcpy(s, hn, l);
231
232 pa_strlcpy(s, a->ai_canonname, l);
233 freeaddrinfo(a);
234 return s;
235 #else
236 return pa_strlcpy(s, hn, l);
237 #endif
238 }
239
240 int pa_msleep(unsigned long t) {
241 #ifdef OS_IS_WIN32
242 Sleep(t);
243 return 0;
244 #elif defined(HAVE_NANOSLEEP)
245 struct timespec ts;
246
247 ts.tv_sec = t/1000;
248 ts.tv_nsec = (t % 1000) * 1000000;
249
250 return nanosleep(&ts, NULL);
251 #else
252 #error "Platform lacks a sleep function."
253 #endif
254 }