1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Library General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Library General Public License for more details.
15
* You should have received a copy of the GNU Library General Public
16
* License along with this library; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
31
#include <glib/gi18n.h>
32
#include <glib/gstdio.h>
34
#include "gdm-common.h"
41
gdm_make_temp_dir (char *template)
43
return mkdtemp (template);
47
gdm_is_version_unstable (void)
54
versions = g_strsplit (VERSION, ".", 3);
55
if (versions && versions [0] && versions [1]) {
57
major = atoi (versions [1]);
58
if ((major % 2) != 0) {
62
g_strfreev (versions);
68
gdm_set_fatal_warnings_if_unstable (void)
70
if (gdm_is_version_unstable ()) {
71
g_setenv ("G_DEBUG", "fatal_criticals", FALSE);
72
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
77
gdm_wait_on_pid (int pid)
83
if (waitpid (pid, &status, 0) < 0) {
86
} else if (errno == ECHILD) {
87
; /* do nothing, child already reaped */
89
g_debug ("GdmCommon: waitpid () should not fail");
93
g_debug ("GdmCommon: process (pid:%d) done (%s:%d)",
95
WIFEXITED (status) ? "status"
96
: WIFSIGNALED (status) ? "signal"
98
WIFEXITED (status) ? WEXITSTATUS (status)
99
: WIFSIGNALED (status) ? WTERMSIG (status)
106
gdm_signal_pid (int pid,
111
/* perhaps block sigchld */
112
g_debug ("GdmCommon: sending signal %d to process %d", signal, pid);
114
status = kill (pid, signal);
117
if (errno == ESRCH) {
118
g_warning ("Child process %d was already dead.",
121
g_warning ("Couldn't kill child process %d: %s",
127
/* perhaps unblock sigchld */
132
/* hex conversion adapted from D-Bus */
134
* Appends a two-character hex digit to a string, where the hex digit
135
* has the value of the given byte.
137
* @param str the string
138
* @param byte the byte
141
_gdm_string_append_byte_as_hex (GString *str,
144
const char hexdigits[16] = {
145
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
146
'a', 'b', 'c', 'd', 'e', 'f'
149
str = g_string_append_c (str, hexdigits[(byte >> 4)]);
151
str = g_string_append_c (str, hexdigits[(byte & 0x0f)]);
155
* Encodes a string in hex, the way MD5 and SHA-1 are usually
156
* encoded. (Each byte is two hex digits.)
158
* @param source the string to encode
159
* @param start byte index to start encoding
160
* @param dest string where encoded data should be placed
161
* @param insert_at where to place encoded data
162
* @returns #TRUE if encoding was successful, #FALSE if no memory etc.
165
gdm_string_hex_encode (const GString *source,
171
const unsigned char *p;
172
const unsigned char *end;
175
g_return_val_if_fail (source != NULL, FALSE);
176
g_return_val_if_fail (dest != NULL, FALSE);
177
g_return_val_if_fail (source != dest, FALSE);
178
g_return_val_if_fail (start >= 0, FALSE);
179
g_return_val_if_fail (dest >= 0, FALSE);
180
g_assert (start <= source->len);
182
result = g_string_new (NULL);
186
p = (const unsigned char*) source->str;
187
end = p + source->len;
191
_gdm_string_append_byte_as_hex (result, *p);
195
dest = g_string_insert (dest, insert_at, result->str);
199
g_string_free (result, TRUE);
205
* Decodes a string from hex encoding.
207
* @param source the string to decode
208
* @param start byte index to start decode
209
* @param end_return return location of the end of the hex data, or #NULL
210
* @param dest string where decoded data should be placed
211
* @param insert_at where to place decoded data
212
* @returns #TRUE if decoding was successful, #FALSE if no memory.
215
gdm_string_hex_decode (const GString *source,
222
const unsigned char *p;
223
const unsigned char *end;
227
g_return_val_if_fail (source != NULL, FALSE);
228
g_return_val_if_fail (dest != NULL, FALSE);
229
g_return_val_if_fail (source != dest, FALSE);
230
g_return_val_if_fail (start >= 0, FALSE);
231
g_return_val_if_fail (dest >= 0, FALSE);
233
g_assert (start <= source->len);
235
result = g_string_new (NULL);
240
p = (const unsigned char*) source->str;
241
end = p + source->len;
307
result = g_string_append_c (result, val << 4);
314
b = result->str[len - 1];
318
result->str[len - 1] = b;
321
high_bits = !high_bits;
327
dest = g_string_insert (dest, insert_at, result->str);
330
*end_return = p - (const unsigned char*) source->str;
335
g_string_free (result, TRUE);
341
_fd_is_character_device (int fd)
343
struct stat file_info;
345
if (fstat (fd, &file_info) < 0) {
349
return S_ISCHR (file_info.st_mode);
355
gsize number_of_bytes,
358
size_t bytes_left_to_read;
359
size_t total_bytes_read = 0;
360
gboolean premature_eof;
362
bytes_left_to_read = number_of_bytes;
363
premature_eof = FALSE;
365
size_t bytes_read = 0;
368
bytes_read = read (fd, ((guchar *) bytes) + total_bytes_read,
371
if (bytes_read > 0) {
372
total_bytes_read += bytes_read;
373
bytes_left_to_read -= bytes_read;
374
} else if (bytes_read == 0) {
375
premature_eof = TRUE;
377
} else if ((errno != EINTR)) {
380
} while (bytes_left_to_read > 0);
385
g_file_error_from_errno (ENODATA),
386
"%s", g_strerror (ENODATA));
389
} else if (bytes_left_to_read > 0) {
392
g_file_error_from_errno (errno),
393
"%s", g_strerror (errno));
401
* Pulls a requested number of bytes from /dev/urandom
403
* @param size number of bytes to pull
404
* @param error error if read fails
405
* @returns The requested number of random bytes or #NULL if fail
409
gdm_generate_random_bytes (gsize size,
416
/* We don't use the g_rand_* glib apis because they don't document
417
* how much entropy they are seeded with, and it might be less
418
* than the passed in size.
422
fd = open ("/dev/urandom", O_RDONLY);
427
g_file_error_from_errno (errno),
428
"%s", g_strerror (errno));
433
if (!_fd_is_character_device (fd)) {
436
g_file_error_from_errno (ENODEV),
437
_("/dev/urandom is not a character device"));
442
bytes = g_malloc (size);
444
if (!_read_bytes (fd, bytes, size, &read_error)) {
445
g_propagate_error (error, read_error);