summaryrefslogtreecommitdiff
path: root/locale/programs/locale.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-02-19 04:43:53 +0000
committerUlrich Drepper <drepper@redhat.com>1997-02-19 04:43:53 +0000
commit1fb05e3db1891142410bc58c320dfe281749fffe (patch)
tree46299dbecec282055e3493787910444e77099fe7 /locale/programs/locale.c
parentc84142e8fe3cbcce43ae35ac957a74ac8216d11d (diff)
update from main archive 970218cvs/libc-970221cvs/libc-970220cvs/libc-970219
1997-02-19 03:28 Miles Bader <miles@gnu.ai.mit.edu> * 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 <drepper@cygnus.com> * 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 <drepper@cygnus.com> * sysdeps/unix/bsd/sun/sunos4/resourcebits.h: Correct #defin to #define. Reported by Rick Flower <FLOWER@sdvax2.sdd.TRW.COM>. 1997-02-19 01:37 Erik Troan <ewt@redhat.com> * shadow/sgetspent_r.c: Accept empty third, fourth and fifth fields. 1997-02-19 01:02 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/mman/syscalls.list: msync takes 3 arguments. Reported by Andreas Jaeger <aj@arthur.pfalz.de>. * sysdeps/stub/msync.c (msync): Add missing third parameter. 1997-02-19 00:29 Ulrich Drepper <drepper@cygnus.com> * sysdeps/unix/bsd/sigsuspend.c: Call __sigpause with needed additional argument. 1997-02-18 22:13 Ulrich Drepper <drepper@cygnus.com> * 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 <asun@zoology.washington.edu>. * sysdeps/unix/sysv/linux/net/if_arp.h: Include <sys/socket.h>. * sunrpc/rpc/rpc_msg.h: Include <rpc/clnt.h>. Reported by a sun <asun@zoology.washington.edu>. 1997-02-16 14:25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * Makerules ((common-objpfx)distinfo-$(subdir)): Depend on sysdep makefiles which may change the distinfo variables. 1997-02-16 14:03 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * 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 <drepper@cygnus.com> * stdio-common/bug10.c (main): Correct parameter. 1997-02-17 02:51 Ulrich Drepper <drepper@cygnus.com> * 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 <asun@zoology.washington.edu> 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 <drepper@cygnus.com> * misc/sys/syslog.h (prioritynames): Correct definition to use braces where necessary. (facilitynames): Likewise. Patch by Ronald F. Guilmette <rfg@monkeys.com>. Comment and beautify declarations. 1997-02-16 19:54 1997 Philip Blundell <Philip.Blundell@pobox.com> * 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 <aj@arthur.pfalz.de> * 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 <drepper@cygnus.com> * 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 <kukuk@weber.uni-paderborn.de> * 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 <andy@tho.org> * 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 <drepper@cygnus.com> * 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 <drepper@cygnus.com> * 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).
Diffstat (limited to 'locale/programs/locale.c')
-rw-r--r--locale/programs/locale.c353
1 files changed, 258 insertions, 95 deletions
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 <drepper@gnu.ai.mit.edu>, 1995.
@@ -22,18 +22,21 @@
# include <config.h>
#endif
+#include <argp.h>
+#include <argz.h>
#include <dirent.h>
+#include <errno.h>
#include <error.h>
-#include <getopt.h>
#include <langinfo.h>
#include <libintl.h>
#include <limits.h>
#include <locale.h>
+#include <search.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
#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 <bugs@gnu.ai.mit.edu>.\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 <bugs@gnu.ai.mit.edu>.\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);
}