1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 2011 Red Hat, Inc.
3 *
4 * glib-unix.c: UNIX specific API wrappers and convenience functions
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but 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 this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authors: Colin Walters <walters@verbum.org>
20 */
21
22#include "config.h"
23
24/* To make bionic export pipe2() */
25#ifndef _GNU_SOURCE
26#define _GNU_SOURCE 1
27#endif
28
29#include "glib-unix.h"
30#include "gmain-internal.h"
31
32#include <string.h>
33#include <sys/types.h>
34#include <pwd.h>
35
36G_STATIC_ASSERT (sizeof (ssize_t) == GLIB_SIZEOF_SSIZE_T);
37G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (ssize_t));
38
39G_STATIC_ASSERT (sizeof (GPid) == sizeof (pid_t));
40G_STATIC_ASSERT (G_ALIGNOF (GPid) == G_ALIGNOF (pid_t));
41
42/**
43 * SECTION:gunix
44 * @title: UNIX-specific utilities and integration
45 * @short_description: pipes, signal handling
46 * @include: glib-unix.h
47 *
48 * Most of GLib is intended to be portable; in contrast, this set of
49 * functions is designed for programs which explicitly target UNIX,
50 * or are using it to build higher level abstractions which would be
51 * conditionally compiled if the platform matches G_OS_UNIX.
52 *
53 * To use these functions, you must explicitly include the
54 * "glib-unix.h" header.
55 */
56
57G_DEFINE_QUARK (g-unix-error-quark, g_unix_error)
58
59static gboolean
60g_unix_set_error_from_errno (GError **error,
61 gint saved_errno)
62{
63 g_set_error_literal (err: error,
64 G_UNIX_ERROR,
65 code: 0,
66 message: g_strerror (errnum: saved_errno));
67 errno = saved_errno;
68 return FALSE;
69}
70
71/**
72 * g_unix_open_pipe:
73 * @fds: Array of two integers
74 * @flags: Bitfield of file descriptor flags, as for fcntl()
75 * @error: a #GError
76 *
77 * Similar to the UNIX pipe() call, but on modern systems like Linux
78 * uses the pipe2() system call, which atomically creates a pipe with
79 * the configured flags. The only supported flag currently is
80 * %FD_CLOEXEC. If for example you want to configure %O_NONBLOCK, that
81 * must still be done separately with fcntl().
82 *
83 * This function does not take %O_CLOEXEC, it takes %FD_CLOEXEC as if
84 * for fcntl(); these are different on Linux/glibc.
85 *
86 * Returns: %TRUE on success, %FALSE if not (and errno will be set).
87 *
88 * Since: 2.30
89 */
90gboolean
91g_unix_open_pipe (int *fds,
92 int flags,
93 GError **error)
94{
95 int ecode;
96
97 /* We only support FD_CLOEXEC */
98 g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE);
99
100#ifdef HAVE_PIPE2
101 {
102 int pipe2_flags = 0;
103 if (flags & FD_CLOEXEC)
104 pipe2_flags |= O_CLOEXEC;
105 /* Atomic */
106 ecode = pipe2 (pipedes: fds, flags: pipe2_flags);
107 if (ecode == -1 && errno != ENOSYS)
108 return g_unix_set_error_from_errno (error, errno);
109 else if (ecode == 0)
110 return TRUE;
111 /* Fall through on -ENOSYS, we must be running on an old kernel */
112 }
113#endif
114 ecode = pipe (pipedes: fds);
115 if (ecode == -1)
116 return g_unix_set_error_from_errno (error, errno);
117
118 if (flags == 0)
119 return TRUE;
120
121 ecode = fcntl (fd: fds[0], F_SETFD, flags);
122 if (ecode == -1)
123 {
124 int saved_errno = errno;
125 close (fd: fds[0]);
126 close (fd: fds[1]);
127 return g_unix_set_error_from_errno (error, saved_errno);
128 }
129 ecode = fcntl (fd: fds[1], F_SETFD, flags);
130 if (ecode == -1)
131 {
132 int saved_errno = errno;
133 close (fd: fds[0]);
134 close (fd: fds[1]);
135 return g_unix_set_error_from_errno (error, saved_errno);
136 }
137 return TRUE;
138}
139
140/**
141 * g_unix_set_fd_nonblocking:
142 * @fd: A file descriptor
143 * @nonblock: If %TRUE, set the descriptor to be non-blocking
144 * @error: a #GError
145 *
146 * Control the non-blocking state of the given file descriptor,
147 * according to @nonblock. On most systems this uses %O_NONBLOCK, but
148 * on some older ones may use %O_NDELAY.
149 *
150 * Returns: %TRUE if successful
151 *
152 * Since: 2.30
153 */
154gboolean
155g_unix_set_fd_nonblocking (gint fd,
156 gboolean nonblock,
157 GError **error)
158{
159#ifdef F_GETFL
160 glong fcntl_flags;
161 fcntl_flags = fcntl (fd: fd, F_GETFL);
162
163 if (fcntl_flags == -1)
164 return g_unix_set_error_from_errno (error, errno);
165
166 if (nonblock)
167 {
168#ifdef O_NONBLOCK
169 fcntl_flags |= O_NONBLOCK;
170#else
171 fcntl_flags |= O_NDELAY;
172#endif
173 }
174 else
175 {
176#ifdef O_NONBLOCK
177 fcntl_flags &= ~O_NONBLOCK;
178#else
179 fcntl_flags &= ~O_NDELAY;
180#endif
181 }
182
183 if (fcntl (fd: fd, F_SETFL, fcntl_flags) == -1)
184 return g_unix_set_error_from_errno (error, errno);
185 return TRUE;
186#else
187 return g_unix_set_error_from_errno (error, EINVAL);
188#endif
189}
190
191/**
192 * g_unix_signal_source_new:
193 * @signum: A signal number
194 *
195 * Create a #GSource that will be dispatched upon delivery of the UNIX
196 * signal @signum. In GLib versions before 2.36, only `SIGHUP`, `SIGINT`,
197 * `SIGTERM` can be monitored. In GLib 2.36, `SIGUSR1` and `SIGUSR2`
198 * were added. In GLib 2.54, `SIGWINCH` was added.
199 *
200 * Note that unlike the UNIX default, all sources which have created a
201 * watch will be dispatched, regardless of which underlying thread
202 * invoked g_unix_signal_source_new().
203 *
204 * For example, an effective use of this function is to handle `SIGTERM`
205 * cleanly; flushing any outstanding files, and then calling
206 * g_main_loop_quit (). It is not safe to do any of this a regular
207 * UNIX signal handler; your handler may be invoked while malloc() or
208 * another library function is running, causing reentrancy if you
209 * attempt to use it from the handler. None of the GLib/GObject API
210 * is safe against this kind of reentrancy.
211 *
212 * The interaction of this source when combined with native UNIX
213 * functions like sigprocmask() is not defined.
214 *
215 * The source will not initially be associated with any #GMainContext
216 * and must be added to one with g_source_attach() before it will be
217 * executed.
218 *
219 * Returns: A newly created #GSource
220 *
221 * Since: 2.30
222 */
223GSource *
224g_unix_signal_source_new (int signum)
225{
226 g_return_val_if_fail (signum == SIGHUP || signum == SIGINT || signum == SIGTERM ||
227 signum == SIGUSR1 || signum == SIGUSR2 || signum == SIGWINCH,
228 NULL);
229
230 return _g_main_create_unix_signal_watch (signum);
231}
232
233/**
234 * g_unix_signal_add_full: (rename-to g_unix_signal_add)
235 * @priority: the priority of the signal source. Typically this will be in
236 * the range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
237 * @signum: Signal number
238 * @handler: Callback
239 * @user_data: Data for @handler
240 * @notify: #GDestroyNotify for @handler
241 *
242 * A convenience function for g_unix_signal_source_new(), which
243 * attaches to the default #GMainContext. You can remove the watch
244 * using g_source_remove().
245 *
246 * Returns: An ID (greater than 0) for the event source
247 *
248 * Since: 2.30
249 */
250guint
251g_unix_signal_add_full (int priority,
252 int signum,
253 GSourceFunc handler,
254 gpointer user_data,
255 GDestroyNotify notify)
256{
257 guint id;
258 GSource *source;
259
260 source = g_unix_signal_source_new (signum);
261
262 if (priority != G_PRIORITY_DEFAULT)
263 g_source_set_priority (source, priority);
264
265 g_source_set_callback (source, func: handler, data: user_data, notify);
266 id = g_source_attach (source, NULL);
267 g_source_unref (source);
268
269 return id;
270}
271
272/**
273 * g_unix_signal_add:
274 * @signum: Signal number
275 * @handler: Callback
276 * @user_data: Data for @handler
277 *
278 * A convenience function for g_unix_signal_source_new(), which
279 * attaches to the default #GMainContext. You can remove the watch
280 * using g_source_remove().
281 *
282 * Returns: An ID (greater than 0) for the event source
283 *
284 * Since: 2.30
285 */
286guint
287g_unix_signal_add (int signum,
288 GSourceFunc handler,
289 gpointer user_data)
290{
291 return g_unix_signal_add_full (G_PRIORITY_DEFAULT, signum, handler, user_data, NULL);
292}
293
294typedef struct
295{
296 GSource source;
297
298 gint fd;
299 gpointer tag;
300} GUnixFDSource;
301
302static gboolean
303g_unix_fd_source_dispatch (GSource *source,
304 GSourceFunc callback,
305 gpointer user_data)
306{
307 GUnixFDSource *fd_source = (GUnixFDSource *) source;
308 GUnixFDSourceFunc func = (GUnixFDSourceFunc) callback;
309
310 if (!callback)
311 {
312 g_warning ("GUnixFDSource dispatched without callback. "
313 "You must call g_source_set_callback().");
314 return FALSE;
315 }
316
317 return (* func) (fd_source->fd, g_source_query_unix_fd (source, tag: fd_source->tag), user_data);
318}
319
320GSourceFuncs g_unix_fd_source_funcs = {
321 NULL, NULL, g_unix_fd_source_dispatch, NULL, NULL, NULL
322};
323
324/**
325 * g_unix_fd_source_new:
326 * @fd: a file descriptor
327 * @condition: IO conditions to watch for on @fd
328 *
329 * Creates a #GSource to watch for a particular IO condition on a file
330 * descriptor.
331 *
332 * The source will never close the fd -- you must do it yourself.
333 *
334 * Returns: the newly created #GSource
335 *
336 * Since: 2.36
337 **/
338GSource *
339g_unix_fd_source_new (gint fd,
340 GIOCondition condition)
341{
342 GUnixFDSource *fd_source;
343 GSource *source;
344
345 source = g_source_new (source_funcs: &g_unix_fd_source_funcs, struct_size: sizeof (GUnixFDSource));
346 fd_source = (GUnixFDSource *) source;
347
348 fd_source->fd = fd;
349 fd_source->tag = g_source_add_unix_fd (source, fd, events: condition);
350
351 return source;
352}
353
354/**
355 * g_unix_fd_add_full:
356 * @priority: the priority of the source
357 * @fd: a file descriptor
358 * @condition: IO conditions to watch for on @fd
359 * @function: a #GUnixFDSourceFunc
360 * @user_data: data to pass to @function
361 * @notify: function to call when the idle is removed, or %NULL
362 *
363 * Sets a function to be called when the IO condition, as specified by
364 * @condition becomes true for @fd.
365 *
366 * This is the same as g_unix_fd_add(), except that it allows you to
367 * specify a non-default priority and a provide a #GDestroyNotify for
368 * @user_data.
369 *
370 * Returns: the ID (greater than 0) of the event source
371 *
372 * Since: 2.36
373 **/
374guint
375g_unix_fd_add_full (gint priority,
376 gint fd,
377 GIOCondition condition,
378 GUnixFDSourceFunc function,
379 gpointer user_data,
380 GDestroyNotify notify)
381{
382 GSource *source;
383 guint id;
384
385 g_return_val_if_fail (function != NULL, 0);
386
387 source = g_unix_fd_source_new (fd, condition);
388
389 if (priority != G_PRIORITY_DEFAULT)
390 g_source_set_priority (source, priority);
391
392 g_source_set_callback (source, func: (GSourceFunc) function, data: user_data, notify);
393 id = g_source_attach (source, NULL);
394 g_source_unref (source);
395
396 return id;
397}
398
399/**
400 * g_unix_fd_add:
401 * @fd: a file descriptor
402 * @condition: IO conditions to watch for on @fd
403 * @function: a #GUnixFDSourceFunc
404 * @user_data: data to pass to @function
405 *
406 * Sets a function to be called when the IO condition, as specified by
407 * @condition becomes true for @fd.
408 *
409 * @function will be called when the specified IO condition becomes
410 * %TRUE. The function is expected to clear whatever event caused the
411 * IO condition to become true and return %TRUE in order to be notified
412 * when it happens again. If @function returns %FALSE then the watch
413 * will be cancelled.
414 *
415 * The return value of this function can be passed to g_source_remove()
416 * to cancel the watch at any time that it exists.
417 *
418 * The source will never close the fd -- you must do it yourself.
419 *
420 * Returns: the ID (greater than 0) of the event source
421 *
422 * Since: 2.36
423 **/
424guint
425g_unix_fd_add (gint fd,
426 GIOCondition condition,
427 GUnixFDSourceFunc function,
428 gpointer user_data)
429{
430 return g_unix_fd_add_full (G_PRIORITY_DEFAULT, fd, condition, function, user_data, NULL);
431}
432
433/**
434 * g_unix_get_passwd_entry:
435 * @user_name: the username to get the passwd file entry for
436 * @error: return location for a #GError, or %NULL
437 *
438 * Get the `passwd` file entry for the given @user_name using `getpwnam_r()`.
439 * This can fail if the given @user_name doesn’t exist.
440 *
441 * The returned `struct passwd` has been allocated using g_malloc() and should
442 * be freed using g_free(). The strings referenced by the returned struct are
443 * included in the same allocation, so are valid until the `struct passwd` is
444 * freed.
445 *
446 * This function is safe to call from multiple threads concurrently.
447 *
448 * You will need to include `pwd.h` to get the definition of `struct passwd`.
449 *
450 * Returns: (transfer full): passwd entry, or %NULL on error; free the returned
451 * value with g_free()
452 * Since: 2.64
453 */
454struct passwd *
455g_unix_get_passwd_entry (const gchar *user_name,
456 GError **error)
457{
458 struct passwd *passwd_file_entry;
459 struct
460 {
461 struct passwd pwd;
462 char string_buffer[];
463 } *buffer = NULL;
464 gsize string_buffer_size = 0;
465 GError *local_error = NULL;
466 int errsv = 0;
467
468 g_return_val_if_fail (user_name != NULL, NULL);
469 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
470
471#ifdef _SC_GETPW_R_SIZE_MAX
472 {
473 /* Get the recommended buffer size */
474 glong string_buffer_size_long = sysconf (_SC_GETPW_R_SIZE_MAX);
475 if (string_buffer_size_long > 0)
476 string_buffer_size = string_buffer_size_long;
477 }
478#endif /* _SC_GETPW_R_SIZE_MAX */
479
480 /* Default starting size. */
481 if (string_buffer_size == 0)
482 string_buffer_size = 64;
483
484 do
485 {
486 int retval;
487
488 g_free (mem: buffer);
489 /* Allocate space for the `struct passwd`, and then a buffer for all its
490 * strings (whose size is @string_buffer_size, which increases in this
491 * loop until it’s big enough). Add 6 extra bytes to work around a bug in
492 * macOS < 10.3. See #156446.
493 */
494 buffer = g_malloc0 (n_bytes: sizeof (*buffer) + string_buffer_size + 6);
495
496 errno = 0;
497 retval = getpwnam_r (name: user_name, resultbuf: &buffer->pwd, buffer: buffer->string_buffer,
498 buflen: string_buffer_size, result: &passwd_file_entry);
499 errsv = errno;
500
501 /* Bail out if: the lookup was successful, or if the user id can't be
502 * found (should be pretty rare case actually), or if the buffer should be
503 * big enough and yet lookups are still not successful.
504 */
505 if (passwd_file_entry != NULL)
506 {
507 /* Success. */
508 break;
509 }
510 else if (retval == 0 ||
511 errsv == ENOENT || errsv == ESRCH ||
512 errsv == EBADF || errsv == EPERM)
513 {
514 /* Username not found. */
515 g_unix_set_error_from_errno (error: &local_error, saved_errno: errsv);
516 break;
517 }
518 else if (errsv == ERANGE)
519 {
520 /* Can’t allocate enough string buffer space. */
521 if (string_buffer_size > 32 * 1024)
522 {
523 g_unix_set_error_from_errno (error: &local_error, saved_errno: errsv);
524 break;
525 }
526
527 string_buffer_size *= 2;
528 continue;
529 }
530 else
531 {
532 g_unix_set_error_from_errno (error: &local_error, saved_errno: errsv);
533 break;
534 }
535 }
536 while (passwd_file_entry == NULL);
537
538 g_assert (passwd_file_entry == NULL ||
539 (gpointer) passwd_file_entry == (gpointer) buffer);
540
541 /* Success or error. */
542 if (local_error != NULL)
543 {
544 g_clear_pointer (&buffer, g_free);
545 g_propagate_error (dest: error, g_steal_pointer (&local_error));
546 errno = errsv;
547 }
548
549 return (struct passwd *) g_steal_pointer (&buffer);
550}
551

source code of gtk/subprojects/glib/glib/glib-unix.c