📄 gconv_conf.c
字号:
need_ext = sizeof (gconv_module_ext) - 1; /* See whether we have already an alias with this name defined. */ old = from; len = strnlen (old, to - from); new = (char *) alloca (len + 1); new[len] = '\0'; fake_alias.fromname = (char *) memcpy (new, old, len); if (tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL) { setlocale(LC_ALL, old_locale); /* This module duplicates an alias. */ return; } new_module = (struct gconv_module *) calloc (1, sizeof (struct gconv_module) + (wp - from) + dir_len + need_ext); if (new_module != NULL) { char *tmp; new_module->from_string = tmp = (char *) (new_module + 1); tmp = memcpy (tmp, from, to - from); tmp += (to - from); new_module->to_string = tmp; tmp = memcpy (tmp, to, module - to); tmp += (module - to); new_module->cost_hi = cost_hi; new_module->cost_lo = modcounter; new_module->module_name = tmp; if (dir_len != 0) { tmp = memcpy (tmp, directory, dir_len); tmp += dir_len; } tmp = memcpy (tmp, module, wp - module); tmp += (wp - module); if (need_ext) memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext)); /* Now insert the new module data structure in our search tree. */ insert_module (new_module, 1); } setlocale(LC_ALL, old_locale);}/* Read the next configuration file. */static voidinternal_functionread_conf_file (const char *filename, const char *directory, size_t dir_len, void **modules, size_t *nmodules){ FILE *fp = fopen (filename, "r"); char *line = NULL; size_t line_len = 0; static int modcounter; char old_locale[20], *old_locale_p; /* Don't complain if a file is not present or readable, simply silently ignore it. */ if (fp == NULL) return; /* Set locale to default C locale. */ old_locale_p = setlocale(LC_ALL, "C"); strncpy(old_locale, old_locale_p, 20); /* Process the known entries of the file. Comments start with `#' and end with the end of the line. Empty lines are ignored. */ while (!feof (fp)) { char *rp, *endp, *word; ssize_t n = __getdelim (&line, &line_len, '\n', fp); if (n < 0) /* An error occurred. */ break; rp = line; /* Terminate the line (excluding comments or newline) by an NUL byte to simplify the following code. */ endp = strchr (rp, '#'); if (endp != NULL) *endp = '\0'; else if (rp[n - 1] == '\n') rp[n - 1] = '\0'; while (isspace (*rp)) ++rp; /* If this is an empty line go on with the next one. */ if (rp == endp) continue; word = rp; while (*rp != '\0' && !isspace (*rp)) ++rp; if (rp - word == sizeof ("alias") - 1 && memcmp (word, "alias", sizeof ("alias") - 1) == 0) add_alias (rp, *modules); else if (rp - word == sizeof ("module") - 1 && memcmp (word, "module", sizeof ("module") - 1) == 0) add_module (rp, directory, dir_len, modules, nmodules, modcounter++); /* else */ /* Otherwise ignore the line. */ } free (line); fclose (fp); setlocale(LC_ALL, old_locale);}/* Determine the directories we are looking for data in. */void__gconv_get_path (void){ struct path_elem *result; __LOCK_INIT(static, path_lock);#ifdef HAVE_DD_LOCK __lock_acquire(path_lock);#endif /* Make sure there wasn't a second thread doing it already. */ result = (struct path_elem *) __gconv_path_elem; if (result == NULL) { /* Determine the complete path first. */ char *gconv_path; size_t gconv_path_len; char *elem; char *oldp; char *cp; int nelems; char *cwd; size_t cwdlen; if (__gconv_path_envvar == NULL) { char * old = default_gconv_path; size_t len = strlen (old) + 1; char *new = (char *) alloca (len); /* No user-defined path. Make a modifiable copy of the default path. */ gconv_path = (char *) memcpy (new, old, len); gconv_path_len = sizeof (default_gconv_path); cwd = NULL; cwdlen = 0; } else { /* Append the default path to the user-defined path. */ size_t user_len = strlen (__gconv_path_envvar); char *tmp; gconv_path_len = user_len + 1 + sizeof (default_gconv_path); gconv_path = alloca (gconv_path_len); tmp = memcpy (gconv_path, __gconv_path_envvar, user_len); tmp += user_len; memcpy (tmp, ":", 1); tmp += 1; memcpy (tmp, default_gconv_path, sizeof (default_gconv_path)); cwd = getcwd (NULL, 0); cwdlen = strlen (cwd); } assert (default_gconv_path[0] == '/'); /* In a first pass we calculate the number of elements. */ oldp = NULL; cp = strchr (gconv_path, ':'); nelems = 1; while (cp != NULL) { if (cp != oldp + 1) ++nelems; oldp = cp; cp = strchr (cp + 1, ':'); } /* Allocate the memory for the result. */ result = (struct path_elem *) malloc ((nelems + 1) * sizeof (struct path_elem) + gconv_path_len + nelems + (nelems - 1) * (cwdlen + 1)); if (result != NULL) { char *strspace = (char *) &result[nelems + 1]; int n = 0; /* Separate the individual parts. */ __gconv_max_path_elem_len = 0; elem = strtok_r (gconv_path, ":", &gconv_path); assert (elem != NULL); do { result[n].name = strspace; if (elem[0] != '/') { assert (cwd != NULL); strspace = memcpy (strspace, cwd, cwdlen); strspace += cwdlen; *strspace++ = '/'; } strspace = strcpy (strspace, elem); while(*strspace != '\0') strspace++; if (strspace[-1] != '/') *strspace++ = '/'; result[n].len = strspace - result[n].name; if (result[n].len > __gconv_max_path_elem_len) __gconv_max_path_elem_len = result[n].len; *strspace++ = '\0'; ++n; } while ((elem = strtok_r (NULL, ":", &gconv_path)) != NULL); result[n].name = NULL; result[n].len = 0; } __gconv_path_elem = result ?: (struct path_elem *) &empty_path_elem; if (cwd != NULL) free (cwd); }#ifdef HAVE_DD_LOCK __lock_release(path_lock);#endif}/* Read all configuration files found in the user-specified and the default path. */void__gconv_read_conf (void){ void *modules = NULL; size_t nmodules = 0; int save_errno = errno; size_t cnt; char *filename; char *tmp; const char *elem; size_t elem_len; /* First see whether we should use the cache. */ if (__gconv_load_cache () == 0) { /* Yes, we are done. */ __set_errno (save_errno); return; }#ifndef STATIC_GCONV /* Find out where we have to look. */ if (__gconv_path_elem == NULL) __gconv_get_path (); for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) { elem = __gconv_path_elem[cnt].name; elem_len = __gconv_path_elem[cnt].len; /* No slash needs to be inserted between elem and gconv_conf_filename; elem already ends in a slash. */ filename = alloca (elem_len + sizeof (gconv_conf_filename)); tmp = memcpy (filename, elem, elem_len); tmp += elem_len; memcpy (tmp, gconv_conf_filename, sizeof (gconv_conf_filename)); /* Read the next configuration file. */ read_conf_file (filename, elem, elem_len, &modules, &nmodules); }#endif /* Add the internal modules. */ for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]); ++cnt) { struct gconv_alias fake_alias; fake_alias.fromname = (char *) builtin_modules[cnt].from_string; if (tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL) /* It'll conflict so don't add it. */ continue; insert_module (&builtin_modules[cnt], 0); } /* Add aliases for builtin conversions. */ cnt = sizeof (builtin_aliases) / sizeof (builtin_aliases[0]); while (cnt > 0) { char * old = builtin_aliases[--cnt]; size_t len = strlen (old) + 1; char *new = (char *) alloca (len); char *copy = (char *) memcpy (new, old, len); add_alias (copy, modules); } /* Restore the error number. */ __set_errno (save_errno);}/* Free all resources if necessary. */static void __attribute__ ((unused))free_mem (void){ if (__gconv_path_elem != NULL && __gconv_path_elem != &empty_path_elem) free ((void *) __gconv_path_elem);}text_set_element (__libc_subfreeres, free_mem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -