mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-07-25 10:16:53 +02:00
.
This commit is contained in:
+563
@@ -0,0 +1,563 @@
|
||||
/* dircolors - parse a Slackware-style DIR_COLORS file.
|
||||
Copyright (C) 1994, 1995 H. Peter Anvin
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "error.h"
|
||||
|
||||
#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 */
|
||||
|
||||
enum modes { mo_sh, mo_csh, mo_ksh, mo_zsh, mo_unknown, mo_err };
|
||||
|
||||
const char *shells[] = { "sh", "ash", "csh", "tcsh", "bash", "ksh",
|
||||
"zsh", NULL };
|
||||
|
||||
const int shell_mode[] = { mo_sh, mo_sh, mo_csh, mo_csh,
|
||||
mo_ksh, mo_ksh, mo_zsh };
|
||||
|
||||
char *program_name;
|
||||
|
||||
|
||||
static void usage __P ((int status));
|
||||
|
||||
|
||||
static int
|
||||
figure_mode (void)
|
||||
{
|
||||
char *shell, *shellv;
|
||||
int i;
|
||||
|
||||
shellv = getenv ("SHELL");
|
||||
if (shellv == NULL || *shellv == '\0')
|
||||
error (1, 0, _("\
|
||||
No SHELL variable, and no mode option specified"));
|
||||
|
||||
shell = strrchr (shellv, '/');
|
||||
if (shell != NULL)
|
||||
++shell;
|
||||
else
|
||||
shell = shellv;
|
||||
|
||||
for (i = 0; shells[i]; ++i)
|
||||
if (strcmp (shell, shells[i]) == 0)
|
||||
return shell_mode[i];
|
||||
|
||||
error (1, 0, _("Unknown shell `%s'\n"), shell);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void
|
||||
parse_line (char **keyword, char **arg, char *line)
|
||||
{
|
||||
char *p;
|
||||
|
||||
*keyword = *arg = "";
|
||||
|
||||
for (p = line; isspace (*p); ++p)
|
||||
;
|
||||
|
||||
if (*p == '\0' || *p == '#')
|
||||
return;
|
||||
|
||||
*keyword = p;
|
||||
|
||||
while (!isspace (*p))
|
||||
if (*p++ == '\0')
|
||||
return;
|
||||
|
||||
*p++ = '\0';
|
||||
|
||||
while (isspace (*p))
|
||||
++p;
|
||||
|
||||
if (*p == '\0' || *p == '#')
|
||||
return;
|
||||
|
||||
*arg = p;
|
||||
|
||||
while (*p != '\0' && *p != '#')
|
||||
++p;
|
||||
for (--p; isspace (*p); --p)
|
||||
;
|
||||
++p;
|
||||
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* Write a string to standard out, while watching for "dangerous"
|
||||
sequences like unescaped : and = characters. */
|
||||
|
||||
static void
|
||||
put_seq (char *str, char follow)
|
||||
{
|
||||
int danger = 1;
|
||||
|
||||
while (*str != '\0')
|
||||
{
|
||||
switch (*str)
|
||||
{
|
||||
case '\\':
|
||||
case '^':
|
||||
danger = !danger;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
case '=':
|
||||
if (danger)
|
||||
putchar ('\\');
|
||||
/* Fall through */
|
||||
|
||||
default:
|
||||
danger = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
putchar (*str++);
|
||||
}
|
||||
|
||||
putchar (follow); /* The character that ends the sequence. */
|
||||
}
|
||||
|
||||
/* Parser needs these state variables. */
|
||||
enum states { st_termno, st_termyes, st_termsure, st_global };
|
||||
|
||||
const char *slack_codes[] = {"NORMAL", "NORM", "FILE", "DIR", "LNK", "LINK",
|
||||
"SYMLINK", "ORPHAN", "MISSING", "FIFO", "PIPE", "SOCK", "BLK", "BLOCK",
|
||||
"CHR", "CHAR", "EXEC", "LEFT", "LEFTCODE", "RIGHT", "RIGHTCODE", "END",
|
||||
"ENDCODE", NULL};
|
||||
|
||||
const char *ls_codes[] = {"no", "no", "fi", "di", "ln", "ln", "ln",
|
||||
"or", "mi", "pi", "pi", "so", "bd", "bd", "cd", "cd", "ex", "lc", "lc", "rc",
|
||||
"rc", "ec", "ec"};
|
||||
|
||||
enum color_opts { col_yes, col_no, col_tty };
|
||||
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"ash", no_argument, NULL, 'a'},
|
||||
{"bash", no_argument, NULL, 'b'},
|
||||
{"csh", no_argument, NULL, 'c'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"no-path", no_argument, NULL, 'P'},
|
||||
{"sh", no_argument, NULL, 's'},
|
||||
{"tcsh", no_argument, NULL, 't'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"zsh", no_argument, NULL, 'z'},
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *p, *q;
|
||||
char *file = NULL;
|
||||
int optc;
|
||||
int mode = mo_unknown;
|
||||
FILE *fp = NULL;
|
||||
char *term;
|
||||
int state;
|
||||
|
||||
char line[STRINGLEN];
|
||||
char useropts[2048] = "";
|
||||
char *keywd, *arg;
|
||||
|
||||
int color_opt = col_no; /* Assume --color=no */
|
||||
|
||||
int no_path = 0; /* Do not search PATH */
|
||||
int do_help = 0;
|
||||
int do_version = 0;
|
||||
|
||||
char *copt;
|
||||
char *input_file;
|
||||
|
||||
program_name = argv[0];
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
/* Parse command line. */
|
||||
|
||||
while ((optc = getopt_long (argc, argv, "abhckPstz", long_options, NULL))
|
||||
!= EOF)
|
||||
switch (optc)
|
||||
{
|
||||
case 'a':
|
||||
case 's': /* Plain sh mode */
|
||||
mode = mo_sh;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
case 't':
|
||||
mode = mo_csh;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'k':
|
||||
mode = mo_ksh;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
do_help = 1;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
mode = mo_zsh;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
no_path = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
do_version = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage (1);
|
||||
}
|
||||
|
||||
/* If version information is wanted show it. */
|
||||
if (do_version)
|
||||
{
|
||||
printf ("%s - %s\n", program_name, PACKAGE_VERSION);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* If help is wanted show the screen. */
|
||||
if (do_help)
|
||||
usage (0);
|
||||
|
||||
/* Use shell to determine mode, if not already done. */
|
||||
if (mode == mo_unknown)
|
||||
mode = figure_mode ();
|
||||
|
||||
/* Open dir_colors file */
|
||||
if (optind == argc)
|
||||
{
|
||||
p = getenv ("HOME");
|
||||
if (p != NULL && *p != '\0')
|
||||
{
|
||||
chdir (p);
|
||||
input_file = USER_FILE;
|
||||
fp = fopen (input_file, "r");
|
||||
}
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
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);
|
||||
|
||||
/* Get terminal type */
|
||||
term = getenv ("TERM");
|
||||
if (term == NULL || *term == '\0')
|
||||
term = "none";
|
||||
|
||||
/* Write out common start */
|
||||
switch (mode)
|
||||
{
|
||||
case mo_csh:
|
||||
puts ("set noglob;\n\
|
||||
setenv LS_COLORS \':");
|
||||
break;
|
||||
case mo_sh:
|
||||
case mo_ksh:
|
||||
case mo_zsh:
|
||||
puts ("LS_COLORS=\'");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start parsing that sucker */
|
||||
state = st_global;
|
||||
|
||||
while (fgets (line, STRINGLEN, fp) != NULL )
|
||||
{
|
||||
parse_line (&keywd, &arg, line);
|
||||
if (*keywd != '\0')
|
||||
{
|
||||
if (strcasecmp (keywd, "TERM") == 0)
|
||||
{
|
||||
if (strcmp (arg, term) == 0)
|
||||
state = st_termsure;
|
||||
else if (state != st_termsure)
|
||||
state = st_termno;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state == st_termsure)
|
||||
state = st_termyes; /* Another TERM can cancel */
|
||||
|
||||
if (state != st_termno)
|
||||
{
|
||||
if (keywd[0] == '.')
|
||||
{
|
||||
putchar ('*');
|
||||
put_seq (keywd, '=');
|
||||
put_seq (arg, ':');
|
||||
}
|
||||
else if (keywd[0] == '*')
|
||||
{
|
||||
put_seq (keywd, '=');
|
||||
put_seq (arg, ':');
|
||||
}
|
||||
else if (strcasecmp(keywd, "OPTIONS") == 0)
|
||||
{
|
||||
strcat (useropts, " ");
|
||||
strcat (useropts, arg);
|
||||
}
|
||||
else if (strcasecmp(keywd, "COLOR") == 0)
|
||||
{
|
||||
switch (arg[0])
|
||||
{
|
||||
case 'a':
|
||||
case 'y':
|
||||
case '1':
|
||||
color_opt = col_yes;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
case '0':
|
||||
color_opt = col_no;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
color_opt = col_tty;
|
||||
break;
|
||||
|
||||
default:
|
||||
error (0, 0, _("Unknown COLOR option `%s'\n"), arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; slack_codes[i] != NULL; ++i)
|
||||
if (strcasecmp (keywd, slack_codes[i]) == 0)
|
||||
break;
|
||||
|
||||
if (slack_codes[i] != NULL)
|
||||
{
|
||||
printf ("%s=", ls_codes[i]);
|
||||
put_seq (arg, ':');
|
||||
}
|
||||
else
|
||||
error (0, 0, _("Unknown keyword %s\n"), keywd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
|
||||
/* Decide on the options. */
|
||||
switch (color_opt)
|
||||
{
|
||||
case col_yes:
|
||||
copt = "--color=yes";
|
||||
break;
|
||||
|
||||
case col_no:
|
||||
copt = "--color=no";
|
||||
break;
|
||||
|
||||
case col_tty:
|
||||
copt = "--color=tty";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find ls in the path. */
|
||||
if (no_path == NULL)
|
||||
{
|
||||
no_path = 1; /* Assume we won't find one. */
|
||||
|
||||
p = getenv ("PATH");
|
||||
if (p != NULL && *p != '\0')
|
||||
{
|
||||
while (*p != '\0')
|
||||
{
|
||||
while (*p == ':')
|
||||
++p;
|
||||
|
||||
if (*p != '/') /* Skip relative path entries. */
|
||||
while (*p != '\0' && *p != ':')
|
||||
++p;
|
||||
else
|
||||
{
|
||||
q = line;
|
||||
while (*p != '\0' && *p != ':')
|
||||
*q++ = *p++;
|
||||
/* Make sure it ends in slash. */
|
||||
if (*(q-1) != '/' )
|
||||
*q++ = '/';
|
||||
|
||||
strcpy (q, "ls");
|
||||
if (access (line, X_OK) == 0)
|
||||
{
|
||||
no_path = 0; /* Found it. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write it out. */
|
||||
switch (mode)
|
||||
{
|
||||
case mo_sh:
|
||||
if (no_path)
|
||||
printf ("\';\n\
|
||||
export LS_COLORS;\n\
|
||||
LS_OPTIONS='%s%s';\n\
|
||||
export LS_OPTIONS;\n\
|
||||
ls () { ( exec ls $LS_OPTIONS \"$@\" ) };\n\
|
||||
dir () { ( exec dir $LS_OPTIONS \"$@\" ) };\n\
|
||||
vdir () { ( exec vdir $LS_OPTIONS \"$@\" ) };\n\
|
||||
d () { dir \"$@\" ; };\n\
|
||||
v () { vdir \"$@\" ; };\n", copt, useropts);
|
||||
else
|
||||
printf ("\';\n\
|
||||
export LS_COLORS;\n\
|
||||
LS_OPTIONS='%s%s';\n\
|
||||
ls () { %s $LS_OPTIONS \"$@\" ; };\n\
|
||||
dir () { %s $LS_OPTIONS --format=vertical \"$@\" ; };\n\
|
||||
vdir () { %s $LS_OPTIONS --format=long \"$@\" ; };\n\
|
||||
d () { dir \"$@\" ; };\n\
|
||||
v () { vdir \"$@\" ; };\n", copt, useropts, line, line, line);
|
||||
break;
|
||||
|
||||
case mo_csh:
|
||||
if (no_path)
|
||||
printf ("\';\n\
|
||||
setenv LS_OPTIONS '%s%s';\n\
|
||||
alias ls \'ls $LS_OPTIONS\';\n\
|
||||
alias dir \'dir $LS_OPTIONS\';\n\
|
||||
alias vdir \'vdir $LS_OPTIONS\';\n\
|
||||
alias d dir;\n\
|
||||
alias v vdir;\n\
|
||||
unset noglob;\n", copt, useropts);
|
||||
else
|
||||
printf ("\';\n\
|
||||
setenv LS_OPTIONS '%s%s';\n\
|
||||
alias ls \'%s $LS_OPTIONS\';\n\
|
||||
alias dir \'%s $LS_OPTIONS --format=vertical\';\n\
|
||||
alias vdir \'%s $LS_OPTIONS --format=long\';\n\
|
||||
alias d dir;\n\
|
||||
alias v vdir;\n\
|
||||
unset noglob;\n", copt, useropts, line, line, line);
|
||||
break;
|
||||
|
||||
case mo_ksh:
|
||||
if (no_path)
|
||||
printf ("\';\n\
|
||||
export LS_COLORS;\n\
|
||||
LS_OPTIONS='%s%s';\n\
|
||||
export LS_OPTIONS;\n\
|
||||
alias ls=\'ls $LS_OPTIONS\';\n\
|
||||
alias dir=\'dir $LS_OPTIONS\';\n\
|
||||
alias vdir=\'vdir $LS_OPTIONS\';\n\
|
||||
alias d=dir;\n\
|
||||
alias v=vdir;\n", copt, useropts);
|
||||
else
|
||||
printf ("\';\n\
|
||||
export LS_COLORS;\n\
|
||||
LS_OPTIONS='%s%s';\n\
|
||||
export LS_OPTIONS;\n\
|
||||
alias ls=\'%s $LS_OPTIONS\';\n\
|
||||
alias dir=\'%s $LS_OPTIONS --format=vertical\';\n\
|
||||
alias vdir=\'%s $LS_OPTIONS --format=long\';\n\
|
||||
alias d=dir;\n\
|
||||
alias v=vdir;\n", copt, useropts, line, line, line);
|
||||
break;
|
||||
|
||||
case mo_zsh:
|
||||
if (no_path)
|
||||
printf ("\';\n\
|
||||
export LS_COLORS;\n\
|
||||
LS_OPTIONS=(%s%s);\n\
|
||||
export LS_OPTIONS;\n\
|
||||
alias ls=\'ls $LS_OPTIONS\';\n\
|
||||
alias dir=\'dir $LS_OPTIONS\';\n\
|
||||
alias vdir=\'vdir $LS_OPTIONS\';\n\
|
||||
alias d=dir;\n\
|
||||
alias v=vdir;\n", copt, useropts);
|
||||
else
|
||||
printf ("\';\n\
|
||||
export LS_COLORS;\n\
|
||||
LS_OPTIONS=(%s%s);\n\
|
||||
export LS_OPTIONS;\n\
|
||||
alias ls=\'%s $LS_OPTIONS\';\n\
|
||||
alias dir=\'%s $LS_OPTIONS --format=vertical\';\n\
|
||||
alias vdir=\'%s $LS_OPTIONS --format=long\';\n\
|
||||
alias d=dir;\n\
|
||||
alias v=vdir;\n", copt, useropts, line, line, line);
|
||||
break;
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
{
|
||||
if (status != 0)
|
||||
fprintf (stderr, _("Try `%s --help' for more information.\n"),
|
||||
program_name);
|
||||
else
|
||||
{
|
||||
printf (_("Usage: %s [OPTION]... [FILE]\n"), program_name);
|
||||
printf (_("\
|
||||
-h, --help display this help and exit\n\
|
||||
-P, --no-path do not look for shell in PATH\n\
|
||||
--version output version information and exit\n\
|
||||
Determine format of output:\n\
|
||||
-a, --ash assume ash shell\n\
|
||||
-b, --bash assume bash shell\n\
|
||||
-c, --csh assume csh shell\n\
|
||||
-s, --sh assume Bourne shell\n\
|
||||
-t, --tcsh assume tcsh shell\n\
|
||||
-z, --zsh assume zsh shell\n"));
|
||||
}
|
||||
|
||||
exit (status);
|
||||
}
|
||||
Reference in New Issue
Block a user