summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1996-06-22 22:02:37 +0000
committerJim Meyering <jim@meyering.net>1996-06-22 22:02:37 +0000
commit98b663a29b5e0982f1c2f4e134d70ce7a453f6af (patch)
tree615c2eecd39345945923ba1c0243decd02464831
parente3c3d0b385565d3d71fee5c7d0d0b4fd69c7a149 (diff)
downloadcoreutils-98b663a29b5e0982f1c2f4e134d70ce7a453f6af.tar.xz
Major overhaul. No longer read from /etc/DIR_COLORS or from ~/.dircolors.
Defaults are now compiled in. If you specify a file on the command line, it is used instead of the compiled-in defaults.
-rw-r--r--src/dircolors.c278
1 files changed, 153 insertions, 125 deletions
diff --git a/src/dircolors.c b/src/dircolors.c
index 8b197217d..a116d6070 100644
--- a/src/dircolors.c
+++ b/src/dircolors.c
@@ -1,7 +1,10 @@
/* FIXME: accept, but ignore EIGHTBIT option
- FIXME: embed contents of default mapping file
FIXME: add option to print that default mapping?
+ dircolors: use compiled-in defaults, output a string setting LS_COLORS
+ dircolors -p: output the compiled-in defaults
+ dircolors FILE: use FILE, output a string setting LS_COLORS
+
Only distinction necessary: Bourne vs. C-shell
Use obstack to accumulate rhs of setenv
*/
@@ -32,18 +35,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include "system.h"
+#include "getline.h"
#include "long-options.h"
#include "error.h"
+#include "dircolors.h"
char *xmalloc ();
+char *basename ();
-#define USER_FILE ".dir_colors" /* Versus user's home directory */
-#define SYSTEM_FILE "DIR_COLORS" /* System-wide file in directory SYSTEM_DIR
- (defined on the cc command line). */
-
-#define STRINGLEN 2048 /* Max length of a string */
+/* Nonzero if any of the files read were the standard input. */
+static int have_read_stdin;
-enum modes { SHELLTYPE_BOURNE, SHELLTYPE_C, SHELLTYPE_UNKNOWN };
+enum Shell_syntax
+{
+ SHELL_SYNTAX_BOURNE,
+ SHELL_SYNTAX_C,
+ SHELL_SYNTAX_UNKNOWN
+};
/* Parser needs these state variables. */
enum states { ST_TERMNO, ST_TERMYES, ST_TERMSURE, ST_GLOBAL };
@@ -93,28 +101,24 @@ Determine format of output:\n\
exit (status);
}
-/* If SHELL is csh or tcsh, assume C-shell. Else Bourne shell. */
+/* If the SHELL environment variable is set to `csh' or `tcsh,'
+ assume C-shell. Else Bourne shell. */
-static int
-figure_mode (void)
+static enum Shell_syntax
+guess_shell_syntax (void)
{
- char *shell, *shellv;
+ char *shell;
- shellv = getenv ("SHELL");
- if (shellv == NULL || *shellv == '\0')
- return SHELLTYPE_UNKNOWN;
+ shell = getenv ("SHELL");
+ if (shell == NULL || *shell == '\0')
+ return SHELL_SYNTAX_UNKNOWN;
- shell = strrchr (shellv, '/');
- if (shell != NULL)
- ++shell;
- else
- shell = shellv;
+ shell = basename (shell);
- if (strcmp (shell, "csh") == 0
- || strcmp (shell, "tcsh") == 0)
- return SHELLTYPE_C;
+ if (STREQ (shell, "csh") || STREQ (shell, "tcsh"))
+ return SHELL_SYNTAX_C;
- return SHELLTYPE_BOURNE;
+ return SHELL_SYNTAX_BOURNE;
}
static void
@@ -189,108 +193,50 @@ put_seq (const char *str, char follow)
putchar (follow); /* The character that ends the sequence. */
}
-int
-main (int argc, char *argv[])
+/* FIXME: Accumulate settings in obstack and convert to string in *RESULT. */
+
+static int
+dc_parse_stream (FILE *fp, const char *filename, char **result)
{
- char *p;
- int optc;
- int mode = SHELLTYPE_UNKNOWN;
- FILE *fp = NULL;
- char *term;
+ size_t line_number = 0;
+ char *line = NULL;
+ size_t line_chars_allocated = 0;
int state;
+ char *term;
+ int err = 0;
- char line[STRINGLEN];
- char *keywd, *arg;
-
- char *input_file;
-
- program_name = argv[0];
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-
- parse_long_options (argc, argv, "dircolors", PACKAGE_VERSION, usage);
-
- while ((optc = getopt_long (argc, argv, "bc", long_options, NULL))
- != EOF)
- switch (optc)
- {
- case 'b': /* Bourne shell mode. */
- mode = SHELLTYPE_BOURNE;
- break;
-
- case 'c': /* Bourne shell mode. */
- mode = SHELLTYPE_C;
- break;
-
- default:
- usage (1);
- }
-
- /* Use shell to determine mode, if not already done. */
- if (mode == SHELLTYPE_UNKNOWN)
- {
- mode = figure_mode ();
- if (mode == SHELLTYPE_UNKNOWN)
- {
- error (1, 0, _("\
-no SHELL environment variable, and no shell type option given"));
- }
- }
-
- /* Open dir_colors file */
- if (optind == argc)
- {
- p = getenv ("HOME");
- if (p != NULL && *p != '\0')
- {
- /* Note: deliberate leak. It's not worth freeing this. */
- input_file = xmalloc (strlen (p) + 1 + strlen (USER_FILE) + 1);
- stpcpy (stpcpy (stpcpy (input_file, p), "/"), USER_FILE);
- fp = fopen (input_file, "r");
- }
-
- if (fp == NULL)
- {
- /* Note: deliberate leak. It's not worth freeing this. */
- input_file = xmalloc (strlen (SHAREDIR) + 1
- + strlen (USER_FILE) + 1);
- stpcpy (stpcpy (stpcpy (input_file, SHAREDIR), "/"),
- SYSTEM_FILE);
- fp = fopen (input_file, "r");
- }
- }
- else
- {
- input_file = argv[optind];
- fp = fopen (input_file, "r");
- }
-
- if (fp == NULL)
- error (1, errno, _("while opening input file `%s'"), input_file);
+ state = ST_GLOBAL;
/* Get terminal type */
term = getenv ("TERM");
if (term == NULL || *term == '\0')
term = "none";
- /* Write out common start */
- switch (mode)
+ while (1)
{
- case SHELLTYPE_C:
- puts ("set noglob;\nsetenv LS_COLORS \':");
- break;
+ int line_length;
+ char *keywd, *arg;
- case SHELLTYPE_BOURNE:
- fputs ("LS_COLORS=\'", stdout);
- break;
- }
+ ++line_number;
- state = ST_GLOBAL;
+ if (fp)
+ {
+ line_length = getline (&line, &line_chars_allocated, fp);
+ if (line_length <= 0)
+ {
+ if (line)
+ free (line);
+ break;
+ }
+ }
+ else
+ {
+ line = (char *) (G_line[line_number - 1]);
+ line_length = G_line_length[line_number - 1];
+ if (line_number > G_N_LINES)
+ break;
+ }
- /* FIXME: use getline */
- while (fgets (line, STRINGLEN, fp) != NULL)
- {
parse_line (&keywd, &arg, line);
if (*keywd != '\0')
{
@@ -341,29 +287,111 @@ no SHELL environment variable, and no shell type option given"));
put_seq (arg, ':');
}
else
- error (0, 0, _("Unknown keyword %s\n"), keywd);
+ {
+ error (0, 0, _("%s:%lu: unrecognized keyword %s\n"),
+ filename, (long unsigned) line_number, keywd);
+ err = 1;
+ }
}
}
}
}
}
- fclose (fp);
+ return err;
+}
+
+static int
+dc_parse_file (const char *filename, char **ls_color_string)
+{
+ FILE *fp;
+ int err;
- /* Write it out. */
- switch (mode)
+ if (strcmp (filename, "-") == 0)
+ {
+ have_read_stdin = 1;
+ fp = stdin;
+ }
+ else
{
- case SHELLTYPE_BOURNE:
- printf ("\';\nexport LS_COLORS\n");
- break;
+ /* OPENOPTS is a macro. It varies with the system.
+ Some systems distinguish between internal and
+ external text representations. */
- case SHELLTYPE_C:
- printf ("\'\nunset noglob\n");
- break;
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ {
+ error (0, errno, "%s", filename);
+ return 1;
+ }
+ }
+
+ err = dc_parse_stream (fp, filename, ls_color_string);
+ if (err)
+ {
+ error (0, errno, "%s", filename);
+ if (fp != stdin)
+ fclose (fp);
+ return 1;
+ }
- default:
- abort ();
+ if (fp != stdin && fclose (fp) == EOF)
+ {
+ error (0, errno, "%s", filename);
+ return 1;
}
- exit (0);
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int err;
+ int optc;
+ enum Shell_syntax syntax = SHELL_SYNTAX_UNKNOWN;
+ char *ls_color_string;
+ char *file;
+
+ program_name = argv[0];
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ parse_long_options (argc, argv, "dircolors", PACKAGE_VERSION, usage);
+
+ while ((optc = getopt_long (argc, argv, "bc", long_options, NULL))
+ != EOF)
+ switch (optc)
+ {
+ case 'b': /* Bourne shell syntax. */
+ syntax = SHELL_SYNTAX_BOURNE;
+ break;
+
+ case 'c': /* C-shell syntax. */
+ syntax = SHELL_SYNTAX_C;
+ break;
+
+ default:
+ usage (1);
+ }
+
+ /* Use shell to determine mode, if not already done. */
+ if (syntax == SHELL_SYNTAX_UNKNOWN)
+ {
+ syntax = guess_shell_syntax ();
+ if (syntax == SHELL_SYNTAX_UNKNOWN)
+ {
+ error (1, 0,
+ _("no SHELL environment variable, and no shell type option given"));
+ }
+ }
+
+ file = argv[optind];
+ err = dc_parse_file (file, &ls_color_string);
+
+ if (have_read_stdin && fclose (stdin) == EOF)
+ error (EXIT_FAILURE, errno, _("standard input"));
+
+ exit (err == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}