From 1fb05e3db1891142410bc58c320dfe281749fffe Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 19 Feb 1997 04:43:53 +0000 Subject: update from main archive 970218 1997-02-19 03:28 Miles Bader * argp/argp-help.c: Add support for user provided filter of help messages. * argp/argp-parse.c: Likewise. * argp/argp.h: Likewise. * argp/argp-namefrob.h: Define __argp_input. * argp/argp-test.c: Add example for filter. 1997-02-19 02:58 Ulrich Drepper * argp.h: New file. * locale/programs/locale.c: Switch to use argp. * errno.h: Make it possible to get definition of error_t even after having errno.h already. * elf/dl-hash.h: New file. ELF hashing function. Extracted from dl-lookup.c. * elf/dl-lookup.c (_dl_elf_hash): Remove definition. * elf/dl-load.c: Rename _dl_does_name_match_p to _dl_name_match_p. * elf/dl-version.c: Likewise. * elf/dl-lookup.c: Implement new versioning lookup scheme. * elf/dl-version.c (_dl_check_map_versions): Initialize new field in l_versions member. * elf/dlvsym.c: Correct call of _dl_lookup_versioned_symbol_skip and _dl_lookup_versioned_symbol. * elf/link.h: Rename hash_name_pair to struct r_found_version. * sysdeps/alpha/dl-machine.h: Likewise. * sysdeps/i386/dl-machine.h: Likewise. * sysdeps/m68k/dl-machine.h: Likewise. * sysdeps/mips/dl-machine.h: Likewise. * intl/l10nflist.c: (_nl_make_l10nflist): Fix bug in computation of length of abs_filename. * locale/Makefile (CPPFLAGS): Define LOCALE_ALIAS_PATH. * locale/programs/ld-monetary.c (monetary_add): Allow value 0 in mon_grouping information. This means no more grouping. * locale/programs/ld-numeric.c (numeric_add): Write value \377 when seein value 0 in grouping information. * locale/programs/linereader.c (lr_close): Don't free fname since it might be used in error messages. * locale/programs/locale.c: Check whether output of `locale -a' really is locale directory. Also print locale aliases. * misc/search.h (__action_fn_t): Parameters VALUE and LEVEL cannot be const. 1997-02-19 02:16 Ulrich Drepper * sysdeps/unix/bsd/sun/sunos4/resourcebits.h: Correct #defin to #define. Reported by Rick Flower . 1997-02-19 01:37 Erik Troan * shadow/sgetspent_r.c: Accept empty third, fourth and fifth fields. 1997-02-19 01:02 Ulrich Drepper * sysdeps/unix/mman/syscalls.list: msync takes 3 arguments. Reported by Andreas Jaeger . * sysdeps/stub/msync.c (msync): Add missing third parameter. 1997-02-19 00:29 Ulrich Drepper * sysdeps/unix/bsd/sigsuspend.c: Call __sigpause with needed additional argument. 1997-02-18 22:13 Ulrich Drepper * inet/net/ethernet.h: New file. * sysdeps/unix/sysv/linux/netinet/if_ether.c: Add BSD compatibility. * sysdeps/unix/sysv/linux/net/if_slip.h: New file. Contributed by a sun . * sysdeps/unix/sysv/linux/net/if_arp.h: Include . * sunrpc/rpc/rpc_msg.h: Include . Reported by a sun . 1997-02-16 14:25 Andreas Schwab * Makerules ((common-objpfx)distinfo-$(subdir)): Depend on sysdep makefiles which may change the distinfo variables. 1997-02-16 14:03 Andreas Schwab * sysdeps/unix/sysv/linux/Makefile (sysdep_headers) [$(subdir)=misc]: Add sys/quota.h. (sysdep_headers) [$(subdir)=inet]: Add netinet/udp.h. 1997-02-17 13:12 aleph1@dfw.net * sunrpc/clnt_simp.c (callrpc): Prevent buffer overflow by using strncpy. 1997-02-18 03:28 Ulrich Drepper * stdio-common/bug10.c (main): Correct parameter. 1997-02-17 02:51 Ulrich Drepper * malloc/obstack.h: Add `extern "C"' protection. * posix/regex.h: Likewise. * io/ftw.h: Likewise. * misc/libgen.h: Likewise. * login/utmp.h: Likewise. * sysdeps/unix/sysv/linux/sys/reboot.h: Likewise. * sysdeps/unix/sysv/linux/netinet/in.h: Likewise. * sunrpc/rpc/pmap_rmt.h: Likewise. * sunrpc/rpc/auth_des.h: Likewise. * elf/link.h: Likewise. Reported by HJ Lu. 1997-02-17 01:45 a sun Linux specific network headers. * sysdeps/unix/sysv/linux/netinet/if_fddi.h: New file. * sysdeps/unix/sysv/linux/netinet/if_tr.h: New file. * sysdeps/unix/sysv/linux/netinet/ip_icmp.h: New file. * sysdeps/unix/sysv/linux/netinet/ip_fw.h: New file. * sysdeps/unix/sysv/linux/netinet/igmp.h: New file. * sysdeps/unix/sysv/linux/netinet/icmp.h: New file. * sysdeps/unix/sysv/linux/netinet/ip.h: New file. * sysdeps/unix/sysv/linux/netinet/tcp.h: New file. * sysdeps/unix/sysv/linux/netipx/ipx.h: New file. * sysdeps/unix/sysv/linux/netatalk/atalk.h: New file. * sysdeps/unix/sysv/linux/Dist: Add new network headers. * sysdeps/unix/sysv/linux/Makefile [$(subdir)=misc] (sysdep_headers): Add sys/quota.h. [$(subdir)=inet] (sysdep_headers): Add new network header. * sysdeps/unix/sysv/linux/netinet/udp.h: Add Linux specific changes. * inet/netinet/ip.h: Move to sysdeps/generic. * inet/netinet/tcp.h: Likewise. * sysdeps/generic/netinet/ip.h: Moved to here from inet/netinet. * sysdeps/generic/netinet/tcp.h: Likewise. 1997-02-17 01:18 Ulrich Drepper * misc/sys/syslog.h (prioritynames): Correct definition to use braces where necessary. (facilitynames): Likewise. Patch by Ronald F. Guilmette . Comment and beautify declarations. 1997-02-16 19:54 1997 Philip Blundell * inet/Makefile (routines): Add in6_addr, getnameinfo. * inet/getnameinfo.c: New file. Implementation of getnameinfo() by Craig Metz. * inet/in6_addr.c: New file. IPv6 addressing constants. * posix/Makefile (routines): Add gai_strerror. * resolv/netdb.h: Add more constants for IPv6 basic API. * sysdeps/posix/gai_strerror.c: New file. * sysdeps/stub/gai_strerror.c New file. * sysdeps/unix/sysv/linux/netinet/in.h: Add definitions for IPv6 basic API. * sysdeps/posix/getaddrinfo.c: Update from latest version by Craig Metz and use reentrant getXXbyYY functions. 1997-02-15 14:32 Andreas Jaeger * argp/argp.h: Declare argp_program_version as const char. * argp/argp-test.c: Likewise * stdlib/testrand.c (main): Declare main prototype. * stdlib/testdiv.c (main): Likewise. * string/testcopy.c (main): Likewise. * string/test-ffs.c (main): Likewise. * time/test_time.c (main): Likewise. * locale/duplocale.c (__duplocale): Return result. 1997-02-16 03:54 Ulrich Drepper * sysdeps/unix/sysv/linux/netinet/in.h: Declare bindresvport. Reported by fabsoft@fabserver1.zarm.uni-bremen.de. * nss/nss.h: Remove declaration of __nss_shlib_revision. * nss/nsswitch.c: Don't use NSS_SHLIB_VERSION macro. 1997-02-16 03:48 Thorsten Kukuk * nis/nss_nis/nis-ethers.c (_nss_nis_getethernam_r): Rename to _nss_nis_gethostton_r. (_nss_nis_getetherbyaddr_r): Rename to _nss_nis_getntohost_r. 1997-02-15 22:37 Andy Berkheimer * resolv/gethnamaddr.c (gethostbyname2): Test for ':' in name before trying to resolv name as numeric IPv6 address. * nss/digits_dots.c: Likewise. Sat Feb 15 04:51:08 1997 Ulrich Drepper * locale/setlocale.c (setlocale): Don't try to be clever about unused locales. When the existence of the locale files isn't tested the result of setlocale might be different. 1997-02-15 03:34 Ulrich Drepper * locale/setlocale.c (setlocale): Don't increment usage_count of new locale if it already has the value MAX_USAGE_COUNT (it might be the C locale data which is read-only). --- locale/programs/locale.c | 353 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 258 insertions(+), 95 deletions(-) (limited to 'locale/programs/locale.c') diff --git a/locale/programs/locale.c b/locale/programs/locale.c index 8587345bf2..5a68c562ef 100644 --- a/locale/programs/locale.c +++ b/locale/programs/locale.c @@ -1,4 +1,4 @@ -/* locale - Implementation of the locale program according to POSIX 1003.2 +/* Implementation of the locale program according to POSIX 1003.2. Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1995. @@ -22,18 +22,21 @@ # include #endif +#include +#include #include +#include #include -#include #include #include #include #include +#include #include #include -#include -#include #include +#include +#include #include "localeinfo.h" @@ -44,16 +47,44 @@ static int show_category_name; /* If set print the name of the item. */ static int show_keyword_name; -/* Long options. */ -static const struct option long_options[] = +/* Print names of all available locales. */ +static int do_all; + +/* Print names of all available character maps. */ +static int do_charmaps = 0; + +/* Name and version of program. */ +static void print_version (FILE *stream, struct argp_state *state); +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Definitions of arguments for argp functions. */ +static struct argp_option options[] = { - { "all-locales", no_argument, NULL, 'a' }, - { "category-name", no_argument, &show_category_name, 1 }, - { "charmaps", no_argument, NULL, 'm' }, - { "help", no_argument, NULL, 'h' }, - { "keyword-name", no_argument, &show_keyword_name, 1 }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } + { NULL, 0, NULL, 0, "System information:" }, + { "all-locales", 'a', NULL, 0, "Write names of available locales" }, + { "charmaps", 'm', NULL, 0, "Write names of available charmaps" }, + { NULL, 0, NULL, 0, "Modify output format:" }, + { "category-name", 'c', NULL, 0, "Write names of selected categories" }, + { "keyword-name", 'k', NULL, 0, "Write names of selected keywords" }, + { NULL, 0, NULL, 0, NULL } +}; + +/* Short description of program. */ +static const char doc[] = "Get locale-specific information."; + +/* Strings for arguments in help texts. */ +static const char args_doc[] = "NAME\n[-a|-m]"; + +/* Prototype for option handler. */ +static error_t parse_opt (int key, char *arg, struct argp_state *state); + +/* Function to print some extra text in the help message. */ +static char *more_help (int key, const char *text, void *input); + +/* Data structure to communicate with argp functions. */ +static struct argp argp = +{ + options, parse_opt, args_doc, doc, NULL, more_help }; @@ -124,7 +155,6 @@ extern void locale_special (const char *name, int show_category_name, int show_keyword_name); /* Prototypes for local functions. */ -static void usage (int status) __attribute__ ((noreturn)); static void write_locales (void); static void write_charmaps (void); static void show_locale_vars (void); @@ -134,12 +164,6 @@ static void show_info (const char *name); int main (int argc, char *argv[]) { - int optchar; - int do_all = 0; - int do_help = 0; - int do_version = 0; - int do_charmaps = 0; - /* Set initial values for global variables. */ show_category_name = 0; show_keyword_name = 0; @@ -152,55 +176,13 @@ main (int argc, char *argv[]) /* Initialize the message catalog. */ textdomain (PACKAGE); - while ((optchar = getopt_long (argc, argv, "achkmV", long_options, NULL)) - != -1) - switch (optchar) - { - case '\0': /* Long option. */ - break; - case 'a': - do_all = 1; - break; - case 'c': - show_category_name = 1; - break; - case 'h': - do_help = 1; - break; - case 'k': - show_keyword_name = 1; - break; - case 'm': - do_charmaps = 1; - break; - case 'V': - do_version = 1; - break; - default: - usage (EXIT_FAILURE); - } - - /* Version information is requested. */ - if (do_version) - { - printf ("locale (GNU %s) %s\n", PACKAGE, VERSION); - printf (_("\ -Copyright (C) %s Free Software Foundation, Inc.\n\ -This is free software; see the source for copying conditions. There is NO\n\ -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "1995, 1996, 1997"); - printf (_("Written by %s.\n"), "Ulrich Drepper"); - - exit (EXIT_SUCCESS); - } - - /* Help is requested. */ - if (do_help) - usage (EXIT_SUCCESS); + /* Parse and process arguments. */ + argp_parse (&argp, argc, argv, 0, 0, NULL); /* `-a' requests the names of all available locales. */ if (do_all != 0) { + setlocale (LC_COLLATE, ""); write_locales (); exit (EXIT_SUCCESS); } @@ -233,61 +215,219 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ } -/* Display usage information and exit. */ -static void -usage (int status) +/* Handle program arguments. */ +static error_t +parse_opt (int key, char *arg, struct argp_state *state) { - if (status != EXIT_SUCCESS) - fprintf (stderr, gettext ("Try `%s --help' for more information.\n"), - __progname); - else + switch (key) { - printf (gettext ("\ -Usage: %s [OPTION]... name\n\ -Mandatory arguments to long options are mandatory for short options too.\n\ - -h, --help display this help and exit\n\ - -V, --version output version information and exit\n\ -\n\ - -a, --all-locales write names of available locales\n\ - -m, --charmaps write names of available charmaps\n\ -\n\ - -c, --category-name write names of selected categories\n\ - -k, --keyword-name write names of selected keywords\n"), - __progname); - fputs (gettext ("\ -Report bugs using the `glibcbug' script to .\n"), - stdout); + case 'a': + do_all = 1; + break; + case 'c': + show_category_name = 1; + break; + case 'm': + do_charmaps = 1; + break; + case 'k': + show_keyword_name = 1; + break; + default: + return ARGP_ERR_UNKNOWN; } + return 0; +} + + +static char * +more_help (int key, const char *text, void *input) +{ + switch (key) + { + case ARGP_KEY_HELP_EXTRA: + /* We print some extra information. */ + return strdup (gettext ("\ +Report bugs using the `glibcbug' script to .\n")); + default: + break; + } + return (char *) text; +} + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "locale (GNU %s) %s\n", PACKAGE, VERSION); + fprintf (stream, gettext ("\ +Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), "1995, 1996, 1997"); + fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); +} - exit (status); + +/* Simple action function which prints arguments as strings. */ +static void +print_names (const void *nodep, VISIT value, int level) +{ + if (value == postorder || value == leaf) + puts (*(char **) nodep); } -/* Write the names of all available locales to stdout. */ +/* Write the names of all available locales to stdout. We have some + sources of the information: the contents of the locale directory + and the locale.alias file. To avoid duplicates and print the + result is a reasonable order we put all entries is a search tree + and print them afterwards. */ static void write_locales (void) { + void *all_data = NULL; DIR *dir; struct dirent *dirent; + char *alias_path; + size_t alias_path_len; + char *entry; - /* `POSIX' locale is always available (POSIX.2 4.34.3). */ - puts ("POSIX"); +#define PUT(name) tsearch ((name), &all_data, \ + (int (*) (const void *, const void *)) strcoll) - dir = opendir (LOCALE_PATH); + dir = opendir (LOCALEDIR); if (dir == NULL) { error (1, errno, gettext ("cannot read locale directory `%s'"), - LOCALE_PATH); + LOCALEDIR); return; } + /* `POSIX' locale is always available (POSIX.2 4.34.3). */ + PUT ("POSIX"); + /* And so is the "C" locale. */ + PUT ("C"); + /* Now we can look for all files in the directory. */ while ((dirent = readdir (dir)) != NULL) if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) - puts (dirent->d_name); + { + mode_t mode; +#ifdef _DIRENT_HAVE_D_TYPE + if (dirent->d_type != DT_UNKNOWN) + mode = DTTOIF (dirent->d_type); + else +#endif + { + struct stat st; + char buf[sizeof (LOCALEDIR) + strlen (dirent->d_name) + 1]; + + stpcpy (stpcpy (stpcpy (buf, LOCALEDIR), "/"), dirent->d_name); + + if (stat (buf, &st) < 0) + continue; + mode = st.st_mode; + } + + if (S_ISDIR (mode)) + PUT (strdup (dirent->d_name)); + } closedir (dir); + + /* Now read the locale.alias files. */ + if (argz_create_sep (LOCALE_ALIAS_PATH, ':', &alias_path, &alias_path_len)) + error (1, errno, gettext ("while preparing output")); + + entry = NULL; + while ((entry = argz_next (alias_path, alias_path_len, entry))) + { + static const char aliasfile[] = "/locale.alias"; + FILE *fp; + char full_name[strlen (entry) + sizeof aliasfile]; + + stpcpy (stpcpy (full_name, entry), aliasfile); + fp = fopen (full_name, "r"); + if (fp == NULL) + /* Ignore non-existing files. */ + continue; + + while (! feof (fp)) + { + /* It is a reasonable approach to use a fix buffer here + because + a) we are only interested in the first two fields + b) these fields must be usable as file names and so must + not be that long */ + char buf[BUFSIZ]; + char *alias; + char *value; + char *cp; + + if (fgets (buf, BUFSIZ, fp) == NULL) + /* EOF reached. */ + break; + + cp = buf; + /* Ignore leading white space. */ + while (isspace (cp[0])) + ++cp; + + /* A leading '#' signals a comment line. */ + if (cp[0] != '\0' && cp[0] != '#') + { + alias = cp++; + while (cp[0] != '\0' && !isspace (cp[0])) + ++cp; + /* Terminate alias name. */ + if (cp[0] != '\0') + *cp++ = '\0'; + + /* Now look for the beginning of the value. */ + while (isspace (cp[0])) + ++cp; + + if (cp[0] != '\0') + { + value = cp++; + while (cp[0] != '\0' && !isspace (cp[0])) + ++cp; + /* Terminate value. */ + if (cp[0] == '\n') + { + /* This has to be done to make the following + test for the end of line possible. We are + looking for the terminating '\n' which do not + overwrite here. */ + *cp++ = '\0'; + *cp = '\n'; + } + else if (cp[0] != '\0') + *cp++ = '\0'; + + /* Add the alias. */ + PUT (strdup (alias)); + } + } + + /* Possibly not the whole line fits into the buffer. + Ignore the rest of the line. */ + while (strchr (cp, '\n') == NULL) + { + cp = buf; + if (fgets (buf, BUFSIZ, fp) == NULL) + /* Make sure the inner loop will be left. The outer + loop will exit at the `feof' test. */ + *cp = '\n'; + } + } + + fclose (fp); + } + + twalk (all_data, print_names); } @@ -295,6 +435,7 @@ write_locales (void) static void write_charmaps (void) { + void *all_data = NULL; DIR *dir; struct dirent *dirent; @@ -310,9 +451,31 @@ write_charmaps (void) while ((dirent = readdir (dir)) != NULL) if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) - puts (dirent->d_name); + { + mode_t mode; +#ifdef _DIRENT_HAVE_D_TYPE + if (dirent->d_type != DT_UNKNOWN) + mode = DTTOIF (dirent->d_type); + else +#endif + { + struct stat st; + char buf[sizeof (CHARMAP_PATH) + strlen (dirent->d_name) + 1]; + + stpcpy (stpcpy (stpcpy (buf, CHARMAP_PATH), "/"), dirent->d_name); + + if (stat (buf, &st) < 0) + continue; + mode = st.st_mode; + } + + if (S_ISREG (mode)) + PUT (strdup (dirent->d_name)); + } closedir (dir); + + twalk (all_data, print_names); } -- cgit v1.2.3