12912Sartem /*************************************************************************** 22912Sartem * CVSID: $Id$ 32912Sartem * 42912Sartem * util.c - Various utilities 52912Sartem * 62912Sartem * Copyright (C) 2004 David Zeuthen, <david@fubar.dk> 72912Sartem * 82912Sartem * Licensed under the Academic Free License version 2.1 92912Sartem * 102912Sartem * This program is free software; you can redistribute it and/or modify 112912Sartem * it under the terms of the GNU General Public License as published by 122912Sartem * the Free Software Foundation; either version 2 of the License, or 132912Sartem * (at your option) any later version. 142912Sartem * 152912Sartem * This program is distributed in the hope that it will be useful, 162912Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of 172912Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 182912Sartem * GNU General Public License for more details. 192912Sartem * 202912Sartem * You should have received a copy of the GNU General Public License 212912Sartem * along with this program; if not, write to the Free Software 222912Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 232912Sartem * 242912Sartem **************************************************************************/ 252912Sartem 262912Sartem #ifdef HAVE_CONFIG_H 272912Sartem # include <config.h> 282912Sartem #endif 292912Sartem 302912Sartem #include <stdio.h> 312912Sartem #include <stdarg.h> 322912Sartem #include <string.h> 332912Sartem #include <errno.h> 342912Sartem #include <time.h> 352912Sartem #include <ctype.h> 362912Sartem #include <stdint.h> 372912Sartem #include <sys/stat.h> 382912Sartem #include <unistd.h> 392912Sartem #include <fcntl.h> 402912Sartem #include <signal.h> 412912Sartem #include <sys/wait.h> 422912Sartem #include <sys/file.h> 432912Sartem 442912Sartem #include <glib.h> 452912Sartem #include <dbus/dbus.h> 462912Sartem #include <dbus/dbus-glib.h> 472912Sartem 482912Sartem #include "osspec.h" 492912Sartem #include "logger.h" 502912Sartem #include "hald.h" 512912Sartem #include "hald_runner.h" 522912Sartem #include "hald_dbus.h" 532912Sartem #include "device_info.h" 542912Sartem 552912Sartem #include "util.h" 562912Sartem 57*10659SXiao-Lin.Zhang@Sun.COM /** Determine whether the given character is valid as the first character 58*10659SXiao-Lin.Zhang@Sun.COM * in a name. 59*10659SXiao-Lin.Zhang@Sun.COM */ 60*10659SXiao-Lin.Zhang@Sun.COM #define VALID_INITIAL_NAME_CHARACTER(c) \ 61*10659SXiao-Lin.Zhang@Sun.COM (((c) >= 'A' && (c) <= 'Z') || \ 62*10659SXiao-Lin.Zhang@Sun.COM ((c) >= 'a' && (c) <= 'z') || \ 63*10659SXiao-Lin.Zhang@Sun.COM ((c) == '_')) 64*10659SXiao-Lin.Zhang@Sun.COM 65*10659SXiao-Lin.Zhang@Sun.COM /** Determine whether the given character is valid as a second or later 66*10659SXiao-Lin.Zhang@Sun.COM * character in a name. 67*10659SXiao-Lin.Zhang@Sun.COM */ 68*10659SXiao-Lin.Zhang@Sun.COM #define VALID_NAME_CHARACTER(c) \ 69*10659SXiao-Lin.Zhang@Sun.COM (((c) >= '0' && (c) <= '9') || \ 70*10659SXiao-Lin.Zhang@Sun.COM ((c) >= 'A' && (c) <= 'Z') || \ 71*10659SXiao-Lin.Zhang@Sun.COM ((c) >= 'a' && (c) <= 'z') || \ 72*10659SXiao-Lin.Zhang@Sun.COM ((c) == '_')) 73*10659SXiao-Lin.Zhang@Sun.COM 742912Sartem gboolean 752912Sartem hal_util_remove_trailing_slash (gchar *path) 762912Sartem { 772912Sartem gchar *c = NULL; 782912Sartem 792912Sartem if (path == NULL) { 802912Sartem return FALSE; 812912Sartem } 822912Sartem 832912Sartem c = strrchr (path, '/'); 842912Sartem if (c == NULL) { 852912Sartem HAL_WARNING (("Invalid path %s", path)); 862912Sartem return 1; 872912Sartem } 882912Sartem if (*(c+1) == '\0') 892912Sartem *c = '\0'; 902912Sartem 912912Sartem return TRUE; 922912Sartem } 932912Sartem 942912Sartem /** Given a path, /foo/bar/bat/foobar, return the last element, e.g. 952912Sartem * foobar. 962912Sartem * 972912Sartem * @param path Path 982912Sartem * @return Pointer into given string 992912Sartem */ 1002912Sartem const gchar * 1012912Sartem hal_util_get_last_element (const gchar *s) 1022912Sartem { 1032912Sartem int len; 1042912Sartem const gchar *p; 1052912Sartem 1062912Sartem len = strlen (s); 1072912Sartem for (p = s + len - 1; p > s; --p) { 1082912Sartem if ((*p) == '/') 1092912Sartem return p + 1; 1102912Sartem } 1112912Sartem 1122912Sartem return s; 1132912Sartem } 1142912Sartem 1152912Sartem /** Given a path, this functions finds the path representing the 1162912Sartem * parent directory by truncation. 1172912Sartem * 1182912Sartem * @param path Path 1192912Sartem * @return Path for parent or NULL. Must be freed by caller 1202912Sartem */ 1212912Sartem gchar * 1222912Sartem hal_util_get_parent_path (const gchar *path) 1232912Sartem { 1242912Sartem guint i; 1252912Sartem guint len; 1262912Sartem gchar *parent_path; 1272912Sartem 1282912Sartem /* Find parent device by truncating our own path */ 1292912Sartem parent_path = g_strndup (path, HAL_PATH_MAX); 1302912Sartem len = strlen (parent_path); 1312912Sartem for (i = len - 1; parent_path[i] != '/'; --i) { 1322912Sartem parent_path[i] = '\0'; 1332912Sartem } 1342912Sartem parent_path[i] = '\0'; 1352912Sartem 1362912Sartem return parent_path; 1372912Sartem } 1382912Sartem 1392912Sartem gchar * 1402912Sartem hal_util_get_normalized_path (const gchar *path1, const gchar *path2) 1412912Sartem { 1422912Sartem int len1; 1432912Sartem int len2; 1442912Sartem const gchar *p1; 1452912Sartem const gchar *p2; 1462912Sartem gchar buf[HAL_PATH_MAX]; 1472912Sartem 1482912Sartem len1 = strlen (path1); 1492912Sartem len2 = strlen (path2); 1502912Sartem 1512912Sartem p1 = path1 + len1; 1522912Sartem 1532912Sartem p2 = path2; 1542912Sartem while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) { 1552912Sartem p2 += 3; 1562912Sartem 1572912Sartem while (p1 >= path1 && *(--p1)!='/') 1582912Sartem ; 1592912Sartem } 1602912Sartem 1612912Sartem if ((p1-path1) < 0) { 1622912Sartem HAL_ERROR (("Could not normalize '%s' and '%s', return 'NULL'", path1, path2)); 1632912Sartem return NULL; 1642912Sartem } 1652912Sartem 1662912Sartem strncpy (buf, path1, (p1-path1)); 1672912Sartem buf[p1-path1] = '\0'; 1682912Sartem 1692912Sartem return g_strdup_printf ("%s/%s", buf, p2); 1702912Sartem } 1712912Sartem 1722912Sartem gboolean 1732912Sartem hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base) 1742912Sartem { 1752912Sartem FILE *f; 1762912Sartem char buf[64]; 1772912Sartem gchar path[HAL_PATH_MAX]; 1782912Sartem gboolean ret; 1792912Sartem 1802912Sartem f = NULL; 1812912Sartem ret = FALSE; 1822912Sartem 1832912Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 1842912Sartem 1852912Sartem f = fopen (path, "rb"); 1862912Sartem if (f == NULL) { 1872912Sartem HAL_ERROR (("Cannot open '%s'", path)); 1882912Sartem goto out; 1892912Sartem } 1902912Sartem 1912912Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 1922912Sartem HAL_ERROR (("Cannot read from '%s'", path)); 1932912Sartem goto out; 1942912Sartem } 1952912Sartem 1962912Sartem /* TODO: handle error condition */ 1972912Sartem *result = strtol (buf, NULL, base); 1982912Sartem ret = TRUE; 1992912Sartem 2002912Sartem out: 2012912Sartem if (f != NULL) 2022912Sartem fclose (f); 2032912Sartem 2042912Sartem return ret; 2052912Sartem } 2062912Sartem 2072912Sartem gboolean 2082912Sartem hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base) 2092912Sartem { 2102912Sartem gint value; 2112912Sartem gboolean ret; 2122912Sartem 2132912Sartem ret = FALSE; 2142912Sartem 2152912Sartem if (hal_util_get_int_from_file (directory, file, &value, base)) 2162912Sartem ret = hal_device_property_set_int (d, key, value); 2172912Sartem 2182912Sartem return ret; 2192912Sartem } 2202912Sartem 2212912Sartem 2222912Sartem gboolean 2232912Sartem hal_util_get_uint64_from_file (const gchar *directory, const gchar *file, guint64 *result, gint base) 2242912Sartem { 2252912Sartem FILE *f; 2262912Sartem char buf[64]; 2272912Sartem gchar path[HAL_PATH_MAX]; 2282912Sartem gboolean ret; 2292912Sartem 2302912Sartem f = NULL; 2312912Sartem ret = FALSE; 2322912Sartem 2332912Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 2342912Sartem 2352912Sartem f = fopen (path, "rb"); 2362912Sartem if (f == NULL) { 2372912Sartem HAL_ERROR (("Cannot open '%s'", path)); 2382912Sartem goto out; 2392912Sartem } 2402912Sartem 2412912Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 2422912Sartem HAL_ERROR (("Cannot read from '%s'", path)); 2432912Sartem goto out; 2442912Sartem } 2452912Sartem 2462912Sartem /* TODO: handle error condition */ 2472912Sartem *result = strtoll (buf, NULL, base); 2482912Sartem 2492912Sartem ret = TRUE; 2502912Sartem 2512912Sartem out: 2522912Sartem if (f != NULL) 2532912Sartem fclose (f); 2542912Sartem 2552912Sartem return ret; 2562912Sartem } 2572912Sartem 2582912Sartem gboolean 2592912Sartem hal_util_set_uint64_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base) 2602912Sartem { 2612912Sartem guint64 value; 2622912Sartem gboolean ret; 2632912Sartem 2642912Sartem ret = FALSE; 2652912Sartem 2662912Sartem if (hal_util_get_uint64_from_file (directory, file, &value, base)) 2672912Sartem ret = hal_device_property_set_uint64 (d, key, value); 2682912Sartem 2692912Sartem return ret; 2702912Sartem } 2712912Sartem 2722912Sartem gboolean 2732912Sartem hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result) 2742912Sartem { 2752912Sartem FILE *f; 2762912Sartem char buf[64]; 2772912Sartem gchar path[HAL_PATH_MAX]; 2782912Sartem gboolean ret; 2792912Sartem gint digit; 2802912Sartem gint left, right; 2812912Sartem gboolean passed_white_space; 2822912Sartem gint num_prec; 2832912Sartem gsize len; 2842912Sartem gchar c; 2852912Sartem guint i; 2862912Sartem 2872912Sartem f = NULL; 2882912Sartem ret = FALSE; 2892912Sartem 2902912Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 2912912Sartem 2922912Sartem f = fopen (path, "rb"); 2932912Sartem if (f == NULL) { 2942912Sartem HAL_ERROR (("Cannot open '%s'", path)); 2952912Sartem goto out; 2962912Sartem } 2972912Sartem 2982912Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 2992912Sartem HAL_ERROR (("Cannot read from '%s'", path)); 3002912Sartem goto out; 3012912Sartem } 3022912Sartem 3032912Sartem left = 0; 3042912Sartem len = strlen (buf); 3052912Sartem passed_white_space = FALSE; 3062912Sartem for (i = 0; i < len && buf[i] != '.'; i++) { 3072912Sartem if (g_ascii_isspace (buf[i])) { 3082912Sartem if (passed_white_space) 3092912Sartem break; 3102912Sartem else 3112912Sartem continue; 3122912Sartem } 3132912Sartem passed_white_space = TRUE; 3142912Sartem left *= 16; 3152912Sartem c = buf[i]; 3162912Sartem digit = (int) (c - '0'); 3172912Sartem left += digit; 3182912Sartem } 3192912Sartem i++; 3202912Sartem right = 0; 3212912Sartem num_prec = 0; 3222912Sartem for (; i < len; i++) { 3232912Sartem if (g_ascii_isspace (buf[i])) 3242912Sartem break; 3252912Sartem if (num_prec == 2) /* Only care about two digits 3262912Sartem * of precision */ 3272912Sartem break; 3282912Sartem right *= 16; 3292912Sartem c = buf[i]; 3302912Sartem digit = (int) (c - '0'); 3312912Sartem right += digit; 3322912Sartem num_prec++; 3332912Sartem } 3342912Sartem 3352912Sartem for (; num_prec < 2; num_prec++) 3362912Sartem right *= 16; 3372912Sartem 3382912Sartem *result = left * 256 + (right & 255); 3392912Sartem ret = TRUE; 3402912Sartem 3412912Sartem out: 3422912Sartem if (f != NULL) 3432912Sartem fclose (f); 3442912Sartem 3452912Sartem return ret; 3462912Sartem } 3472912Sartem 3482912Sartem gboolean 3492912Sartem hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file) 3502912Sartem { 3512912Sartem gint value; 3522912Sartem gboolean ret; 3532912Sartem 3542912Sartem ret = FALSE; 3552912Sartem 3562912Sartem if (hal_util_get_bcd2_from_file (directory, file, &value)) 3572912Sartem ret = hal_device_property_set_int (d, key, value); 3582912Sartem 3592912Sartem return ret; 3602912Sartem } 3612912Sartem 3622912Sartem gchar * 3632912Sartem hal_util_get_string_from_file (const gchar *directory, const gchar *file) 3642912Sartem { 3652912Sartem FILE *f; 3662912Sartem static gchar buf[256]; 3672912Sartem gchar path[HAL_PATH_MAX]; 3682912Sartem gchar *result; 3692912Sartem gsize len; 3702912Sartem gint i; 3712912Sartem 3722912Sartem f = NULL; 3732912Sartem result = NULL; 3742912Sartem 3752912Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 3762912Sartem 3772912Sartem f = fopen (path, "rb"); 3782912Sartem if (f == NULL) { 3792912Sartem HAL_ERROR (("Cannot open '%s'", path)); 3802912Sartem goto out; 3812912Sartem } 3822912Sartem 3832912Sartem buf[0] = '\0'; 3842912Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 3852912Sartem HAL_ERROR (("Cannot read from '%s'", path)); 3862912Sartem goto out; 3872912Sartem } 3882912Sartem 3892912Sartem len = strlen (buf); 3902912Sartem if (len>0) 3912912Sartem buf[len-1] = '\0'; 3922912Sartem 3932912Sartem /* Clear remaining whitespace */ 3942912Sartem for (i = len - 2; i >= 0; --i) { 3952912Sartem if (!g_ascii_isspace (buf[i])) 3962912Sartem break; 3972912Sartem buf[i] = '\0'; 3982912Sartem } 3992912Sartem 4002912Sartem result = buf; 4012912Sartem 4022912Sartem out: 4032912Sartem if (f != NULL) 4042912Sartem fclose (f); 4052912Sartem 4062912Sartem return result; 4072912Sartem } 4082912Sartem 4092912Sartem gboolean 4102912Sartem hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file) 4112912Sartem { 4122912Sartem gchar *buf; 4132912Sartem gboolean ret; 4142912Sartem 4152912Sartem ret = FALSE; 4162912Sartem 4172912Sartem if ((buf = hal_util_get_string_from_file (directory, file)) != NULL) 4182912Sartem ret = hal_device_property_set_string (d, key, buf); 4192912Sartem 4202912Sartem return ret; 4212912Sartem } 4222912Sartem 4232912Sartem void 4242912Sartem hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...) 4252912Sartem { 4262912Sartem guint i; 4272912Sartem va_list args; 4282912Sartem gchar buf[256]; 4292912Sartem 4302912Sartem va_start (args, format); 4312912Sartem g_vsnprintf (buf, sizeof (buf), format, args); 4322912Sartem va_end (args); 4332912Sartem 4342912Sartem g_strcanon (buf, 4352912Sartem "/_" 4362912Sartem "abcdefghijklmnopqrstuvwxyz" 4372912Sartem "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 4382912Sartem "1234567890", '_'); 4392912Sartem 4402912Sartem g_strlcpy (dst, buf, dstsize); 4412912Sartem if (hal_device_store_find (store, dst) == NULL) 4422912Sartem goto out; 4432912Sartem 4442912Sartem for (i = 0; ; i++) { 4452912Sartem g_snprintf (dst, dstsize, "%s_%d", buf, i); 4462912Sartem if (hal_device_store_find (store, dst) == NULL) 4472912Sartem goto out; 4482912Sartem } 4492912Sartem 4502912Sartem out: 4512912Sartem ; 4522912Sartem } 4532912Sartem 4542912Sartem 4552912Sartem gboolean 4562912Sartem hal_util_path_ascend (gchar *path) 4572912Sartem { 4582912Sartem gchar *p; 4592912Sartem 4602912Sartem if (path == NULL) 4612912Sartem return FALSE; 4622912Sartem 4632912Sartem p = strrchr (path, '/'); 4642912Sartem if (p == NULL) 4652912Sartem return FALSE; 4662912Sartem 4672912Sartem *p = '\0'; 4682912Sartem return TRUE; 4692912Sartem } 4702912Sartem 4712912Sartem static gboolean _grep_can_reuse = FALSE; 4722912Sartem 4732912Sartem void 4742912Sartem hal_util_grep_discard_existing_data (void) 4752912Sartem { 4762912Sartem _grep_can_reuse = FALSE; 4772912Sartem } 4782912Sartem 4792912Sartem /** Given a directory and filename, open the file and search for the 4802912Sartem * first line that starts with the given linestart string. Returns 4812912Sartem * the rest of the line as a string if found. 4822912Sartem * 4832912Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 4842912Sartem * @param file File, e.g. "info" 4852912Sartem * @param linestart Start of line, e.g. "serial number" 4862912Sartem * @param reuse Whether we should reuse the file contents 4872912Sartem * if the file is the same; can be cleared 4882912Sartem * with hal_util_grep_discard_existing_data() 4892912Sartem * @return NULL if not found, otherwise the remainder 4902912Sartem * of the line, e.g. ": 21805" if 4912912Sartem * the file /proc/acpi/battery/BAT0 contains 4922912Sartem * this line "serial number: 21805" 4932912Sartem * The string is only valid until the next 4942912Sartem * invocation of this function. 4952912Sartem */ 4962912Sartem gchar * 4972912Sartem hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart, gboolean reuse) 4982912Sartem { 4992912Sartem static gchar buf[2048]; 5002912Sartem static unsigned int bufsize; 5012912Sartem static gchar filename[HAL_PATH_MAX]; 5022912Sartem static gchar oldfilename[HAL_PATH_MAX]; 5032912Sartem gchar *result; 5042912Sartem gsize linestart_len; 5052912Sartem gchar *p; 5062912Sartem 5072912Sartem result = NULL; 5082912Sartem 5092912Sartem /* TODO: use reuse and _grep_can_reuse parameters to avoid loading 5102912Sartem * the file again and again 5112912Sartem */ 5122912Sartem 5132912Sartem if (file != NULL && strlen (file) > 0) 5142912Sartem snprintf (filename, sizeof (filename), "%s/%s", directory, file); 5152912Sartem else 5162912Sartem strncpy (filename, directory, sizeof (filename)); 5172912Sartem 5182912Sartem if (_grep_can_reuse && reuse && strcmp (oldfilename, filename) == 0) { 5192912Sartem /* just reuse old file; e.g. bufsize, buf */ 5202912Sartem /*HAL_INFO (("hal_util_grep_file: reusing buf for %s", filename));*/ 5212912Sartem } else { 5222912Sartem FILE *f; 5232912Sartem 5242912Sartem f = fopen (filename, "r"); 5252912Sartem if (f == NULL) 5262912Sartem goto out; 5272912Sartem bufsize = fread (buf, sizeof (char), sizeof (buf) - 1, f); 5282912Sartem buf[bufsize] = '\0'; 5292912Sartem fclose (f); 5302912Sartem 5312912Sartem /*HAL_INFO (("hal_util_grep_file: read %s of %d bytes", filename, bufsize));*/ 5322912Sartem } 5332912Sartem 5342912Sartem /* book keeping */ 5352912Sartem _grep_can_reuse = TRUE; 5362912Sartem strncpy (oldfilename, filename, sizeof(oldfilename)); 5372912Sartem 5382912Sartem linestart_len = strlen (linestart); 5392912Sartem 5402912Sartem /* analyze buf */ 5412912Sartem p = buf; 5422912Sartem do { 5432912Sartem unsigned int linelen; 5442912Sartem static char line[256]; 5452912Sartem 5462912Sartem for (linelen = 0; p[linelen] != '\n' && p[linelen] != '\0'; linelen++) 5472912Sartem ; 5482912Sartem 5492912Sartem if (linelen < sizeof (line)) { 5502912Sartem 5512912Sartem strncpy (line, p, linelen); 5522912Sartem line[linelen] = '\0'; 5532912Sartem 5542912Sartem if (strncmp (line, linestart, linestart_len) == 0) { 5552912Sartem result = line + linestart_len; 5562912Sartem goto out; 5572912Sartem } 5582912Sartem } 5592912Sartem 5602912Sartem p += linelen + 1; 5612912Sartem 5622912Sartem } while (p < buf + bufsize); 5632912Sartem 5642912Sartem out: 5652912Sartem return result; 5662912Sartem } 5672912Sartem 5682912Sartem gchar * 5692912Sartem hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file, 5702912Sartem const gchar *linestart, guint elem, gboolean reuse) 5712912Sartem { 5722912Sartem gchar *line; 5732912Sartem gchar *res; 5742912Sartem static gchar buf[256]; 5752912Sartem gchar **tokens; 5762912Sartem guint i, j; 5772912Sartem 5782912Sartem res = NULL; 5792912Sartem tokens = NULL; 5802912Sartem 5812912Sartem if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0)) 5822912Sartem goto out; 5832912Sartem 5842912Sartem tokens = g_strsplit_set (line, " \t:", 0); 5852912Sartem for (i = 0, j = 0; tokens[i] != NULL; i++) { 5862912Sartem if (strlen (tokens[i]) == 0) 5872912Sartem continue; 5882912Sartem if (j == elem) { 5892912Sartem strncpy (buf, tokens[i], sizeof (buf)); 5902912Sartem res = buf; 5912912Sartem goto out; 5922912Sartem } 5932912Sartem j++; 5942912Sartem } 5952912Sartem 5962912Sartem out: 5972912Sartem if (tokens != NULL) 5982912Sartem g_strfreev (tokens); 5992912Sartem 6002912Sartem return res; 6012912Sartem } 6022912Sartem 6032912Sartem gint 6042912Sartem hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file, 6052912Sartem const gchar *linestart, guint elem, guint base, gboolean reuse) 6062912Sartem { 6072912Sartem gchar *endptr; 6082912Sartem gchar *strvalue; 6092912Sartem int value; 6102912Sartem 6112912Sartem value = G_MAXINT; 6122912Sartem 6132912Sartem strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse); 6142912Sartem if (strvalue == NULL) 6152912Sartem goto out; 6162912Sartem 6172912Sartem value = strtol (strvalue, &endptr, base); 6182912Sartem if (endptr == strvalue) { 6192912Sartem value = G_MAXINT; 6202912Sartem goto out; 6212912Sartem } 6222912Sartem 6232912Sartem out: 6242912Sartem return value; 6252912Sartem } 6262912Sartem 6272912Sartem /** Get a string value from a formatted text file and assign it to 6282912Sartem * a property on a device object. 6292912Sartem * 6302912Sartem * Example: Given that the file /proc/acpi/battery/BAT0/info contains 6312912Sartem * the line 6322912Sartem * 6332912Sartem * "design voltage: 10800 mV" 6342912Sartem * 6352912Sartem * then hal_util_set_string_elem_from_file (d, "battery.foo", 6362912Sartem * "/proc/acpi/battery/BAT0", "info", "design voltage", 1) will assign 6372912Sartem * the string "mV" to the property "battery.foo" on d. 6382912Sartem * 6392912Sartem * @param d Device object 6402912Sartem * @param key Property name 6412912Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 6422912Sartem * @param file File, e.g. "info" 6432912Sartem * @param linestart Start of line, e.g. "design voltage" 6442912Sartem * @param elem Element number after linestart to extract 6452912Sartem * excluding whitespace and ':' characters. 6462912Sartem * @return TRUE, if, and only if, the value could be 6472912Sartem * extracted and the property was set 6482912Sartem */ 6492912Sartem gboolean 6502912Sartem hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key, 6512912Sartem const gchar *directory, const gchar *file, 6522912Sartem const gchar *linestart, guint elem, gboolean reuse) 6532912Sartem { 6542912Sartem gboolean res; 6552912Sartem gchar *value; 6562912Sartem 6572912Sartem res = FALSE; 6582912Sartem 6592912Sartem if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse)) == NULL) 6602912Sartem goto out; 6612912Sartem 6622912Sartem res = hal_device_property_set_string (d, key, value); 6632912Sartem out: 6642912Sartem return res; 6652912Sartem } 6662912Sartem 6672912Sartem /** Get an integer value from a formatted text file and assign it to 6682912Sartem * a property on a device object. 6692912Sartem * 6702912Sartem * Example: Given that the file /proc/acpi/battery/BAT0/info contains 6712912Sartem * the line 6722912Sartem * 6732912Sartem * "design voltage: 10800 mV" 6742912Sartem * 6752912Sartem * then hal_util_set_int_elem_from_file (d, "battery.foo", 6762912Sartem * "/proc/acpi/battery/BAT0", "info", "design voltage", 0) will assign 6772912Sartem * the integer 10800 to the property "battery.foo" on d. 6782912Sartem * 6792912Sartem * @param d Device object 6802912Sartem * @param key Property name 6812912Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 6822912Sartem * @param file File, e.g. "info" 6832912Sartem * @param linestart Start of line, e.g. "design voltage" 6842912Sartem * @param elem Element number after linestart to extract 6852912Sartem * excluding whitespace and ':' characters. 6862912Sartem * @return TRUE, if, and only if, the value could be 6872912Sartem * extracted and the property was set 6882912Sartem */ 6892912Sartem gboolean 6902912Sartem hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key, 6912912Sartem const gchar *directory, const gchar *file, 6922912Sartem const gchar *linestart, guint elem, guint base, gboolean reuse) 6932912Sartem { 6942912Sartem gchar *endptr; 6952912Sartem gboolean res; 6962912Sartem gchar *strvalue; 6972912Sartem int value; 6982912Sartem 6992912Sartem res = FALSE; 7002912Sartem 7012912Sartem strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse); 7022912Sartem if (strvalue == NULL) 7032912Sartem goto out; 7042912Sartem 7052912Sartem value = strtol (strvalue, &endptr, base); 7062912Sartem if (endptr == strvalue) 7072912Sartem goto out; 7082912Sartem 7092912Sartem res = hal_device_property_set_int (d, key, value); 7102912Sartem 7112912Sartem out: 7122912Sartem return res; 7132912Sartem 7142912Sartem } 7152912Sartem 7162912Sartem /** Get a value from a formatted text file, test it against a given 7172912Sartem * value, and set a boolean property on a device object with the 7182912Sartem * test result. 7192912Sartem * 7202912Sartem * Example: Given that the file /proc/acpi/battery/BAT0/info contains 7212912Sartem * the line 7222912Sartem * 7232912Sartem * "present: yes" 7242912Sartem * 7252912Sartem * then hal_util_set_bool_elem_from_file (d, "battery.baz", 7262912Sartem * "/proc/acpi/battery/BAT0", "info", "present", 0, "yes") will assign 7272912Sartem * the boolean TRUE to the property "battery.baz" on d. 7282912Sartem * 7292912Sartem * If, instead, the line was 7302912Sartem * 7312912Sartem * "present: no" 7322912Sartem * 7332912Sartem * the value assigned will be FALSE. 7342912Sartem * 7352912Sartem * @param d Device object 7362912Sartem * @param key Property name 7372912Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 7382912Sartem * @param file File, e.g. "info" 7392912Sartem * @param linestart Start of line, e.g. "design voltage" 7402912Sartem * @param elem Element number after linestart to extract 7412912Sartem * excluding whitespace and ':' characters. 7422912Sartem * @param expected Value to test against 7432912Sartem * @return TRUE, if, and only if, the value could be 7442912Sartem * extracted and the property was set 7452912Sartem */ 7462912Sartem gboolean 7472912Sartem hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key, 7482912Sartem const gchar *directory, const gchar *file, 7492912Sartem const gchar *linestart, guint elem, const gchar *expected, gboolean reuse) 7502912Sartem { 7512912Sartem gchar *line; 7522912Sartem gboolean res; 7532912Sartem gchar **tokens; 7542912Sartem guint i, j; 7552912Sartem 7562912Sartem res = FALSE; 7572912Sartem tokens = NULL; 7582912Sartem 7592912Sartem if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0)) 7602912Sartem goto out; 7612912Sartem 7622912Sartem tokens = g_strsplit_set (line, " \t:", 0); 7632912Sartem 7642912Sartem for (i = 0, j = 0; tokens[i] != NULL; i++) { 7652912Sartem if (strlen (tokens[i]) == 0) 7662912Sartem continue; 7672912Sartem if (j == elem) { 7682912Sartem hal_device_property_set_bool (d, key, strcmp (tokens[i], expected) == 0); 7692912Sartem res = TRUE; 7702912Sartem goto out; 7712912Sartem } 7722912Sartem j++; 7732912Sartem } 7742912Sartem 7752912Sartem 7762912Sartem out: 7772912Sartem if (tokens != NULL) 7782912Sartem g_strfreev (tokens); 7792912Sartem 7802912Sartem return res; 7812912Sartem } 7822912Sartem 7832912Sartem gchar ** 7842912Sartem hal_util_dup_strv_from_g_slist (GSList *strlist) 7852912Sartem { 7862912Sartem guint j; 7872912Sartem guint len; 7882912Sartem gchar **strv; 7892912Sartem GSList *i; 7902912Sartem 7912912Sartem len = g_slist_length (strlist); 7922912Sartem strv = g_new (char *, len + 1); 7932912Sartem 7942912Sartem for (i = strlist, j = 0; i != NULL; i = g_slist_next (i), j++) { 7952912Sartem strv[j] = g_strdup ((const gchar *) i->data); 7962912Sartem } 7972912Sartem strv[j] = NULL; 7982912Sartem 7992912Sartem return strv; 8002912Sartem } 8012912Sartem 8022912Sartem /* -------------------------------------------------------------------------------------------------------------- */ 8032912Sartem 8042912Sartem typedef struct { 8052912Sartem HalDevice *d; 8062912Sartem gchar **programs; 8072912Sartem gchar **extra_env; 8082912Sartem guint next_program; 8092912Sartem 8102912Sartem HalCalloutsDone callback; 8112912Sartem gpointer userdata1; 8122912Sartem gpointer userdata2; 8132912Sartem 8142912Sartem } Callout; 8152912Sartem 8162912Sartem static void callout_do_next (Callout *c); 8172912Sartem 8182912Sartem static void 8192912Sartem callout_terminated (HalDevice *d, guint32 exit_type, 8202912Sartem gint return_code, gchar **error, 8212912Sartem gpointer data1, gpointer data2) 8222912Sartem { 8232912Sartem Callout *c; 8242912Sartem 8252912Sartem c = (Callout *) data1; 8262912Sartem callout_do_next (c); 8272912Sartem } 8282912Sartem 8292912Sartem static void 8302912Sartem callout_do_next (Callout *c) 8312912Sartem { 8322912Sartem 8332912Sartem /* Check if we're done */ 8342912Sartem if (c->programs[c->next_program] == NULL) { 8352912Sartem HalDevice *d; 8362912Sartem gpointer userdata1; 8372912Sartem gpointer userdata2; 8382912Sartem HalCalloutsDone callback; 8392912Sartem 8402912Sartem d = c->d; 8412912Sartem userdata1 = c->userdata1; 8422912Sartem userdata2 = c->userdata2; 8432912Sartem callback = c->callback; 8442912Sartem 8452912Sartem g_strfreev (c->programs); 8462912Sartem g_strfreev (c->extra_env); 8472912Sartem g_free (c); 8482912Sartem 8492912Sartem callback (d, userdata1, userdata2); 8502912Sartem 8512912Sartem } else { 8522912Sartem hald_runner_run(c->d, c->programs[c->next_program], c->extra_env, 8532912Sartem HAL_HELPER_TIMEOUT, callout_terminated, 8542912Sartem (gpointer)c, NULL); 8552912Sartem c->next_program++; 8562912Sartem } 8572912Sartem } 8582912Sartem 8592912Sartem static void 8602912Sartem hal_callout_device (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2, 8612912Sartem GSList *programs, gchar **extra_env) 8622912Sartem { 8632912Sartem Callout *c; 8642912Sartem 8652912Sartem c = g_new0 (Callout, 1); 8662912Sartem c->d = d; 8672912Sartem c->callback = callback; 8682912Sartem c->userdata1 = userdata1; 8692912Sartem c->userdata2 = userdata2; 8702912Sartem c->programs = hal_util_dup_strv_from_g_slist (programs); 8712912Sartem c->extra_env = g_strdupv (extra_env); 8722912Sartem c->next_program = 0; 8732912Sartem 8742912Sartem callout_do_next (c); 8752912Sartem } 8762912Sartem 8772912Sartem void 8782912Sartem hal_util_callout_device_add (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2) 8792912Sartem { 8802912Sartem GSList *programs; 8812912Sartem gchar *extra_env[2] = {"HALD_ACTION=add", NULL}; 8822912Sartem 8832912Sartem if ((programs = hal_device_property_get_strlist (d, "info.callouts.add")) == NULL) { 8842912Sartem callback (d, userdata1, userdata2); 8852912Sartem goto out; 8862912Sartem } 8872912Sartem 8882912Sartem HAL_INFO (("Add callouts for udi=%s", d->udi)); 8892912Sartem 8902912Sartem hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env); 8912912Sartem out: 8922912Sartem ; 8932912Sartem } 8942912Sartem 8952912Sartem void 8962912Sartem hal_util_callout_device_remove (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2) 8972912Sartem { 8982912Sartem GSList *programs; 8992912Sartem gchar *extra_env[2] = {"HALD_ACTION=remove", NULL}; 9002912Sartem 9012912Sartem if ((programs = hal_device_property_get_strlist (d, "info.callouts.remove")) == NULL) { 9022912Sartem callback (d, userdata1, userdata2); 9032912Sartem goto out; 9042912Sartem } 9052912Sartem 9062912Sartem HAL_INFO (("Remove callouts for udi=%s", d->udi)); 9072912Sartem 9082912Sartem hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env); 9092912Sartem out: 9102912Sartem ; 9112912Sartem } 9122912Sartem 9132912Sartem void 9142912Sartem hal_util_callout_device_preprobe (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2) 9152912Sartem { 9162912Sartem GSList *programs; 9172912Sartem gchar *extra_env[2] = {"HALD_ACTION=preprobe", NULL}; 9182912Sartem 9192912Sartem if ((programs = hal_device_property_get_strlist (d, "info.callouts.preprobe")) == NULL) { 9202912Sartem callback (d, userdata1, userdata2); 9212912Sartem goto out; 9222912Sartem } 9232912Sartem 9242912Sartem HAL_INFO (("Preprobe callouts for udi=%s", d->udi)); 9252912Sartem 9262912Sartem hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env); 9272912Sartem out: 9282912Sartem ; 9292912Sartem } 9302912Sartem 9312912Sartem gchar * 9322912Sartem hal_util_strdup_valid_utf8 (const char *str) 9332912Sartem { 9342912Sartem char *endchar; 9352912Sartem char *newstr; 9362912Sartem unsigned int count = 0; 9372912Sartem 9382912Sartem if (str == NULL) 9392912Sartem return NULL; 9402912Sartem 9412912Sartem newstr = g_strdup (str); 9422912Sartem 9432912Sartem while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) { 9442912Sartem *endchar = '?'; 9452912Sartem count++; 9462912Sartem } 9472912Sartem 9482912Sartem if (strlen(newstr) == count) 9492912Sartem return NULL; 9502912Sartem else 9512912Sartem return newstr; 9522912Sartem } 9532912Sartem 9542912Sartem void 9552912Sartem hal_util_hexdump (const void *mem, unsigned int size) 9562912Sartem { 9572912Sartem unsigned int i; 9582912Sartem unsigned int j; 9592912Sartem unsigned int n; 9602912Sartem const char *buf = (const char *) mem; 9612912Sartem 9622912Sartem n = 0; 9632912Sartem printf ("Dumping %d=0x%x bytes\n", size, size); 9642912Sartem while (n < size) { 9652912Sartem 9662912Sartem printf ("0x%04x: ", n); 9672912Sartem 9682912Sartem j = n; 9692912Sartem for (i = 0; i < 16; i++) { 9702912Sartem if (j >= size) 9712912Sartem break; 9722912Sartem printf ("%02x ", buf[j]); 9732912Sartem j++; 9742912Sartem } 9752912Sartem 9762912Sartem for ( ; i < 16; i++) { 9772912Sartem printf (" "); 9782912Sartem } 9792912Sartem 9802912Sartem printf (" "); 9812912Sartem 9822912Sartem j = n; 9832912Sartem for (i = 0; i < 16; i++) { 9842912Sartem if (j >= size) 9852912Sartem break; 9862912Sartem printf ("%c", isprint(buf[j]) ? buf[j] : '.'); 9872912Sartem j++; 9882912Sartem } 9892912Sartem 9902912Sartem printf ("\n"); 9912912Sartem 9922912Sartem n += 16; 9932912Sartem } 9942912Sartem } 9952912Sartem 9962912Sartem gboolean 9972912Sartem hal_util_is_mounted_by_hald (const char *mount_point) 9982912Sartem { 9992912Sartem int i; 10002912Sartem FILE *hal_mtab; 10012912Sartem int hal_mtab_len; 10022912Sartem int num_read; 10032912Sartem char *hal_mtab_buf; 10042912Sartem char **lines; 10052912Sartem gboolean found; 10062912Sartem 10072912Sartem hal_mtab = NULL; 10082912Sartem hal_mtab_buf = NULL; 10092912Sartem found = FALSE; 10102912Sartem 10112912Sartem /*HAL_DEBUG (("examining /media/.hal-mtab for %s", mount_point));*/ 10122912Sartem 10132912Sartem hal_mtab = fopen ("/media/.hal-mtab", "r"); 10142912Sartem if (hal_mtab == NULL) { 10152912Sartem HAL_ERROR (("Cannot open /media/.hal-mtab")); 10162912Sartem goto out; 10172912Sartem } 10182912Sartem if (fseek (hal_mtab, 0L, SEEK_END) != 0) { 10192912Sartem HAL_ERROR (("Cannot seek to end of /media/.hal-mtab")); 10202912Sartem goto out; 10212912Sartem } 10222912Sartem hal_mtab_len = ftell (hal_mtab); 10232912Sartem if (hal_mtab_len < 0) { 10242912Sartem HAL_ERROR (("Cannot determine size of /media/.hal-mtab")); 10252912Sartem goto out; 10262912Sartem } 10272912Sartem rewind (hal_mtab); 10282912Sartem 10292912Sartem hal_mtab_buf = g_new0 (char, hal_mtab_len + 1); 10302912Sartem num_read = fread (hal_mtab_buf, 1, hal_mtab_len, hal_mtab); 10312912Sartem if (num_read != hal_mtab_len) { 10322912Sartem HAL_ERROR (("Cannot read from /media/.hal-mtab")); 10332912Sartem goto out; 10342912Sartem } 10352912Sartem fclose (hal_mtab); 10362912Sartem hal_mtab = NULL; 10372912Sartem 10382912Sartem /*HAL_DEBUG (("hal_mtab = '%s'\n", hal_mtab_buf));*/ 10392912Sartem 10402912Sartem lines = g_strsplit (hal_mtab_buf, "\n", 0); 10412912Sartem g_free (hal_mtab_buf); 10422912Sartem hal_mtab_buf = NULL; 10432912Sartem 10442912Sartem /* find the entry we're going to unmount */ 10452912Sartem for (i = 0; lines[i] != NULL && !found; i++) { 10462912Sartem char **line_elements; 10472912Sartem 10482912Sartem /*HAL_DEBUG ((" line = '%s'", lines[i]));*/ 10492912Sartem 10502912Sartem if ((lines[i])[0] == '#') 10512912Sartem continue; 10522912Sartem 10532912Sartem line_elements = g_strsplit (lines[i], "\t", 6); 10542912Sartem if (g_strv_length (line_elements) == 6) { 10552912Sartem /* 10562912Sartem HAL_DEBUG ((" devfile = '%s'", line_elements[0])); 10572912Sartem HAL_DEBUG ((" uid = '%s'", line_elements[1])); 10582912Sartem HAL_DEBUG ((" session id = '%s'", line_elements[2])); 10592912Sartem HAL_DEBUG ((" fs = '%s'", line_elements[3])); 10602912Sartem HAL_DEBUG ((" options = '%s'", line_elements[4])); 10612912Sartem HAL_DEBUG ((" mount_point = '%s'", line_elements[5])); 10622912Sartem HAL_DEBUG ((" (comparing against '%s')", mount_point)); 10632912Sartem */ 10642912Sartem 10652912Sartem if (strcmp (line_elements[5], mount_point) == 0) { 10662912Sartem found = TRUE; 10672912Sartem /*HAL_INFO (("device at '%s' is indeed mounted by HAL's Mount()", mount_point));*/ 10682912Sartem } 10692912Sartem 10702912Sartem } 10712912Sartem 10722912Sartem g_strfreev (line_elements); 10732912Sartem } 10742912Sartem 10752912Sartem g_strfreev (lines); 10762912Sartem 10772912Sartem out: 10782912Sartem if (hal_mtab != NULL) 10792912Sartem fclose (hal_mtab); 10802912Sartem if (hal_mtab_buf != NULL) 10812912Sartem g_free (hal_mtab_buf); 10822912Sartem 10832912Sartem return found; 10842912Sartem } 10852912Sartem 10862912Sartem void 10872912Sartem hal_util_branch_claim (HalDeviceStore *store, HalDevice *root, dbus_bool_t claimed, 10882912Sartem const char *service, int uid) 10892912Sartem { 10902912Sartem GSList *children; 10912912Sartem GSList *i; 10922912Sartem HalDevice *d; 10932912Sartem 10942912Sartem if (claimed) { 10952912Sartem hal_device_property_set_bool (root, "info.claimed", claimed); 10962912Sartem hal_device_property_set_string (root, "info.claimed.service", service); 10972912Sartem hal_device_property_set_int (root, "info.claimed.uid", uid); 10982912Sartem } else { 10992912Sartem hal_device_property_remove (root, "info.claimed"); 11002912Sartem hal_device_property_remove (root, "info.claimed.service"); 11012912Sartem hal_device_property_remove (root, "info.claimed.uid"); 11022912Sartem } 11032912Sartem 11042912Sartem 11052912Sartem children = hal_device_store_match_multiple_key_value_string (store, 11062912Sartem "info.parent", root->udi); 11072912Sartem 11082912Sartem for (i = children; i != NULL; i = g_slist_next (i)) { 11092912Sartem d = HAL_DEVICE (i->data); 11102912Sartem hal_util_branch_claim (store, d, claimed, service, uid); 11112912Sartem } 11122912Sartem 11132912Sartem g_slist_free (children); 11142912Sartem } 1115*10659SXiao-Lin.Zhang@Sun.COM 1116*10659SXiao-Lin.Zhang@Sun.COM /** Given an interface name, check if it is valid. 1117*10659SXiao-Lin.Zhang@Sun.COM * @param name A given interface name 1118*10659SXiao-Lin.Zhang@Sun.COM * @return TRUE if name is valid, otherwise FALSE 1119*10659SXiao-Lin.Zhang@Sun.COM */ 1120*10659SXiao-Lin.Zhang@Sun.COM gboolean 1121*10659SXiao-Lin.Zhang@Sun.COM is_valid_interface_name(const char *name) { 1122*10659SXiao-Lin.Zhang@Sun.COM 1123*10659SXiao-Lin.Zhang@Sun.COM const char *end; 1124*10659SXiao-Lin.Zhang@Sun.COM const char *last_dot; 1125*10659SXiao-Lin.Zhang@Sun.COM 1126*10659SXiao-Lin.Zhang@Sun.COM last_dot = NULL; 1127*10659SXiao-Lin.Zhang@Sun.COM 1128*10659SXiao-Lin.Zhang@Sun.COM if (strlen(name) == 0) 1129*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1130*10659SXiao-Lin.Zhang@Sun.COM 1131*10659SXiao-Lin.Zhang@Sun.COM end = name + strlen(name); 1132*10659SXiao-Lin.Zhang@Sun.COM 1133*10659SXiao-Lin.Zhang@Sun.COM if (*name == '.') /* disallow starting with a . */ 1134*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1135*10659SXiao-Lin.Zhang@Sun.COM else if (!VALID_INITIAL_NAME_CHARACTER (*name)) 1136*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1137*10659SXiao-Lin.Zhang@Sun.COM else 1138*10659SXiao-Lin.Zhang@Sun.COM name++; 1139*10659SXiao-Lin.Zhang@Sun.COM 1140*10659SXiao-Lin.Zhang@Sun.COM while (name != end) { 1141*10659SXiao-Lin.Zhang@Sun.COM if (*name == '.') { 1142*10659SXiao-Lin.Zhang@Sun.COM if ((name + 1) == end) 1143*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1144*10659SXiao-Lin.Zhang@Sun.COM else if (!VALID_INITIAL_NAME_CHARACTER (*(name + 1))) 1145*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1146*10659SXiao-Lin.Zhang@Sun.COM last_dot = name; 1147*10659SXiao-Lin.Zhang@Sun.COM name++; /* we just validated the next char, so skip two */ 1148*10659SXiao-Lin.Zhang@Sun.COM } else if (!VALID_NAME_CHARACTER (*name)) 1149*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1150*10659SXiao-Lin.Zhang@Sun.COM name++; 1151*10659SXiao-Lin.Zhang@Sun.COM } 1152*10659SXiao-Lin.Zhang@Sun.COM if (last_dot == NULL) 1153*10659SXiao-Lin.Zhang@Sun.COM return FALSE; 1154*10659SXiao-Lin.Zhang@Sun.COM 1155*10659SXiao-Lin.Zhang@Sun.COM return TRUE; 1156*10659SXiao-Lin.Zhang@Sun.COM } 1157