]> code.delx.au - pulseaudio/blob - src/polyp/util.c
split polypcore/util.[ch] into polypcore/core-util.[ch] and polyp/util.[ch]
[pulseaudio] / src / polyp / util.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio 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 polypaudio 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 polypaudio; 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 <stdarg.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <errno.h>
30 #include <assert.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <limits.h>
36 #include <time.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/time.h>
41
42 #ifdef HAVE_NETDB_H
43 #include <netdb.h>
44 #endif
45
46 #ifdef HAVE_PWD_H
47 #include <pwd.h>
48 #endif
49
50 #ifdef HAVE_GRP_H
51 #include <grp.h>
52 #endif
53
54 #ifdef HAVE_WINDOWS_H
55 #include <windows.h>
56 #endif
57
58 #include <polyp/xmalloc.h>
59 #include <polypcore/log.h>
60 #include <polypcore/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 /* Return the current username in the specified string buffer. */
71 char *pa_get_user_name(char *s, size_t l) {
72 char *p;
73 char buf[1024];
74
75 #ifdef HAVE_PWD_H
76 struct passwd pw, *r;
77 #endif
78
79 assert(s && l > 0);
80
81 if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
82 #ifdef HAVE_PWD_H
83
84 #ifdef HAVE_GETPWUID_R
85 if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
86 #else
87 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
88 * that do not support getpwuid_r. */
89 if ((r = getpwuid(getuid())) == NULL) {
90 #endif
91 snprintf(s, l, "%lu", (unsigned long) getuid());
92 return s;
93 }
94
95 p = r->pw_name;
96
97 #elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
98 DWORD size = sizeof(buf);
99
100 if (!GetUserName(buf, &size))
101 return NULL;
102
103 p = buf;
104
105 #else /* HAVE_PWD_H */
106 return NULL;
107 #endif /* HAVE_PWD_H */
108 }
109
110 return pa_strlcpy(s, p, l);
111 }
112
113 /* Return the current hostname in the specified buffer. */
114 char *pa_get_host_name(char *s, size_t l) {
115 assert(s && l > 0);
116 if (gethostname(s, l) < 0) {
117 pa_log(__FILE__": gethostname(): %s", strerror(errno));
118 return NULL;
119 }
120 s[l-1] = 0;
121 return s;
122 }
123
124 /* Return the home directory of the current user */
125 char *pa_get_home_dir(char *s, size_t l) {
126 char *e;
127
128 #ifdef HAVE_PWD_H
129 char buf[1024];
130 struct passwd pw, *r;
131 #endif
132
133 assert(s && l);
134
135 if ((e = getenv("HOME")))
136 return pa_strlcpy(s, e, l);
137
138 if ((e = getenv("USERPROFILE")))
139 return pa_strlcpy(s, e, l);
140
141 #ifdef HAVE_PWD_H
142 #ifdef HAVE_GETPWUID_R
143 if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
144 pa_log(__FILE__": getpwuid_r() failed");
145 #else
146 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
147 * that do not support getpwuid_r. */
148 if ((r = getpwuid(getuid())) == NULL) {
149 pa_log(__FILE__": getpwuid_r() failed");
150 #endif
151 return NULL;
152 }
153
154 return pa_strlcpy(s, r->pw_dir, l);
155 #else /* HAVE_PWD_H */
156 return NULL;
157 #endif
158 }
159
160 struct timeval *pa_gettimeofday(struct timeval *tv) {
161 #ifdef HAVE_GETTIMEOFDAY
162 assert(tv);
163
164 return gettimeofday(tv, NULL) < 0 ? NULL : tv;
165 #elif defined(OS_IS_WIN32)
166 /*
167 * Copied from implementation by Steven Edwards (LGPL).
168 * Found on wine mailing list.
169 */
170
171 #if defined(_MSC_VER) || defined(__BORLANDC__)
172 #define EPOCHFILETIME (116444736000000000i64)
173 #else
174 #define EPOCHFILETIME (116444736000000000LL)
175 #endif
176
177 FILETIME ft;
178 LARGE_INTEGER li;
179 __int64 t;
180
181 assert(tv);
182
183 GetSystemTimeAsFileTime(&ft);
184 li.LowPart = ft.dwLowDateTime;
185 li.HighPart = ft.dwHighDateTime;
186 t = li.QuadPart; /* In 100-nanosecond intervals */
187 t -= EPOCHFILETIME; /* Offset to the Epoch time */
188 t /= 10; /* In microseconds */
189 tv->tv_sec = (long)(t / 1000000);
190 tv->tv_usec = (long)(t % 1000000);
191
192 return tv;
193 #else
194 #error "Platform lacks gettimeofday() or equivalent function."
195 #endif
196 }
197
198 /* Calculate the difference between the two specfified timeval
199 * timestamsps. */
200 pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
201 pa_usec_t r;
202 assert(a && b);
203
204 /* Check which whan is the earlier time and swap the two arguments if reuqired. */
205 if (pa_timeval_cmp(a, b) < 0) {
206 const struct timeval *c;
207 c = a;
208 a = b;
209 b = c;
210 }
211
212 /* Calculate the second difference*/
213 r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000;
214
215 /* Calculate the microsecond difference */
216 if (a->tv_usec > b->tv_usec)
217 r += ((pa_usec_t) a->tv_usec - b->tv_usec);
218 else if (a->tv_usec < b->tv_usec)
219 r -= ((pa_usec_t) b->tv_usec - a->tv_usec);
220
221 return r;
222 }
223
224 /* Compare the two timeval structs and return 0 when equal, negative when a < b, positive otherwse */
225 int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
226 assert(a && b);
227
228 if (a->tv_sec < b->tv_sec)
229 return -1;
230
231 if (a->tv_sec > b->tv_sec)
232 return 1;
233
234 if (a->tv_usec < b->tv_usec)
235 return -1;
236
237 if (a->tv_usec > b->tv_usec)
238 return 1;
239
240 return 0;
241 }
242
243 /* Return the time difference between now and the specified timestamp */
244 pa_usec_t pa_timeval_age(const struct timeval *tv) {
245 struct timeval now;
246 assert(tv);
247
248 return pa_timeval_diff(pa_gettimeofday(&now), tv);
249 }
250
251 /* Add the specified time inmicroseconds to the specified timeval structure */
252 void pa_timeval_add(struct timeval *tv, pa_usec_t v) {
253 unsigned long secs;
254 assert(tv);
255
256 secs = (v/1000000);
257 tv->tv_sec += (unsigned long) secs;
258 v -= secs*1000000;
259
260 tv->tv_usec += v;
261
262 /* Normalize */
263 while (tv->tv_usec >= 1000000) {
264 tv->tv_sec++;
265 tv->tv_usec -= 1000000;
266 }
267 }
268
269 /* Return the binary file name of the current process. Works on Linux
270 * only. This shoul be used for eyecandy only, don't rely on return
271 * non-NULL! */
272 char *pa_get_binary_name(char *s, size_t l) {
273
274 #ifdef HAVE_READLINK
275 char path[PATH_MAX];
276 int i;
277 assert(s && l);
278
279 /* This works on Linux only */
280
281 snprintf(path, sizeof(path), "/proc/%u/exe", (unsigned) getpid());
282 if ((i = readlink(path, s, l-1)) < 0)
283 return NULL;
284
285 s[i] = 0;
286 return s;
287 #elif defined(OS_IS_WIN32)
288 char path[PATH_MAX];
289 if (!GetModuleFileName(NULL, path, PATH_MAX))
290 return NULL;
291 pa_strlcpy(s, pa_path_get_filename(path), l);
292 return s;
293 #else
294 return NULL;
295 #endif
296 }
297
298 /* Return a pointer to the filename inside a path (which is the last
299 * component). */
300 const char *pa_path_get_filename(const char *p) {
301 char *fn;
302
303 if ((fn = strrchr(p, PATH_SEP)))
304 return fn+1;
305
306 return (const char*) p;
307 }
308
309 /* Return the fully qualified domain name in *s */
310 char *pa_get_fqdn(char *s, size_t l) {
311 char hn[256];
312 #ifdef HAVE_GETADDRINFO
313 struct addrinfo *a, hints;
314 #endif
315
316 if (!pa_get_host_name(hn, sizeof(hn)))
317 return NULL;
318
319 #ifdef HAVE_GETADDRINFO
320 memset(&hints, 0, sizeof(hints));
321 hints.ai_family = AF_UNSPEC;
322 hints.ai_flags = AI_CANONNAME;
323
324 if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname)
325 return pa_strlcpy(s, hn, l);
326
327 pa_strlcpy(s, a->ai_canonname, l);
328 freeaddrinfo(a);
329 return s;
330 #else
331 return pa_strlcpy(s, hn, l);
332 #endif
333 }
334
335 /* Wait t milliseconds */
336 int pa_msleep(unsigned long t) {
337 #ifdef OS_IS_WIN32
338 Sleep(t);
339 return 0;
340 #elif defined(HAVE_NANOSLEEP)
341 struct timespec ts;
342
343 ts.tv_sec = t/1000;
344 ts.tv_nsec = (t % 1000) * 1000000;
345
346 return nanosleep(&ts, NULL);
347 #else
348 #error "Platform lacks a sleep function."
349 #endif
350 }