]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
.
authorJim Meyering <jim@meyering.net>
Mon, 29 Apr 1996 04:04:59 +0000 (04:04 +0000)
committerJim Meyering <jim@meyering.net>
Mon, 29 Apr 1996 04:04:59 +0000 (04:04 +0000)
src/dircolors.c [new file with mode: 0644]

diff --git a/src/dircolors.c b/src/dircolors.c
new file mode 100644 (file)
index 0000000..ce54413
--- /dev/null
@@ -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);
+}