]> git.refcnt.org Git - colorize.git/blobdiff - colorize.c
Display type and name of file in error messages
[colorize.git] / colorize.c
index 9e0c294ba0ca89e5322b52481adcb00346a3fdc5..69aca359feb79deb8128623a1f47dfeffc18fcb0 100644 (file)
@@ -2,7 +2,7 @@
  * colorize - Read text from standard input stream or file and print
  *            it colorized through use of ANSI escape sequences
  *
- * Copyright (c) 2011-2013 Steven Schubiger
+ * Copyright (c) 2011-2014 Steven Schubiger
  *
  * 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
@@ -68,6 +68,8 @@
 
 #define SKIP_LINE_ENDINGS(flags) (((flags) & CR) && ((flags) & LF) ? 2 : 1)
 
+#define VALID_FILE_TYPE(mode) (S_ISREG (mode) || S_ISLNK (mode) || S_ISFIFO (mode))
+
 #define STACK_VAR(ptr) do {                                   \
     stack_var (&vars_list, &stacked_vars, stacked_vars, ptr); \
 } while (false)
@@ -96,7 +98,7 @@
 
 #define COLOR_SEP_CHAR '/'
 
-#define VERSION "0.52"
+#define VERSION "0.53"
 
 typedef enum { false, true } bool;
 
@@ -139,17 +141,21 @@ static const struct color bg_colors[] = {
 
 enum fmts {
     FMT_GENERIC,
+    FMT_QUOTE,
     FMT_COLOR,
     FMT_RANDOM,
     FMT_ERROR,
-    FMT_FILE
+    FMT_FILE,
+    FMT_TYPE
 };
 static const char *formats[] = {
     "%s",                    /* generic */
+    "%s `%s' %s",            /* quote   */
     "%s color '%s' %s",      /* color   */
     "%s color '%s' %s '%s'", /* random  */
     "less than %u bytes %s", /* error   */
     "%s: %s",                /* file    */
+    "%s: %s: %s",            /* type    */
 };
 
 enum { FOREGROUND, BACKGROUND };
@@ -175,6 +181,7 @@ static char *exclude = NULL;
 
 static const char *program_name;
 
+static void print_hint (void);
 static void print_help (void);
 static void print_version (void);
 static void cleanup (void);
@@ -196,6 +203,7 @@ static void *realloc_wrap_debug (void *, size_t, const char *, unsigned int);
 static void free_wrap (void **);
 static char *strdup_wrap (const char *);
 static char *str_concat (const char *, const char *);
+static char *get_file_type (mode_t);
 static bool has_color_name (const char *, const char *);
 static void vfprintf_diag (const char *, ...);
 static void vfprintf_fail (const char *, ...);
@@ -210,6 +218,8 @@ static void release_var (void **, unsigned int, void **);
 extern char *optarg;
 extern int optind;
 
+static int opt_type = 0;
+
 int
 main (int argc, char **argv)
 {
@@ -223,7 +233,7 @@ main (int argc, char **argv)
         OPT_VERSION
     };
 
-    int opt, opt_type = 0;
+    int opt;
     struct option long_opts[] = {
         { "clean",          no_argument,       &opt_type, OPT_CLEAN          },
         { "clean-all",      no_argument,       &opt_type, OPT_CLEAN_ALL      },
@@ -294,7 +304,7 @@ main (int argc, char **argv)
             case 'v':
               SET_OPT_TYPE (OPT_VERSION);
             case '?':
-              print_help ();
+              print_hint ();
               exit (EXIT_FAILURE);
             default: /* never reached */
               ABORT_TRACE ();
@@ -321,8 +331,8 @@ main (int argc, char **argv)
       {
         if (arg_cnt == 0 || arg_cnt > 2)
           {
-            vfprintf_diag ("%u arguments provided, expected 1-2 arguments or option", arg_cnt);
-            print_help ();
+            vfprintf_diag ("%u arguments provided, expected 1-2 arguments or clean option", arg_cnt);
+            print_hint ();
             exit (EXIT_FAILURE);
           }
       }
@@ -338,6 +348,12 @@ main (int argc, char **argv)
     exit (EXIT_SUCCESS);
 }
 
+static void
+print_hint (void)
+{
+    fprintf (stderr, "Type `%s --help' for help screen.\n", program_name);
+}
+
 static void
 print_help (void)
 {
@@ -442,7 +458,7 @@ process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct
           vfprintf_fail (formats[FMT_GENERIC], "hyphen must be preceeded by color string");
       }
 
-    ret = stat (color_string, &sb);
+    ret = lstat (color_string, &sb);
 
     /* Ensure that we don't fail if there's a file with one or more
        color names in its path.  */
@@ -451,6 +467,7 @@ process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct
         bool have_file;
         unsigned int c;
         const char *color = color_string;
+        const mode_t mode = sb.st_mode;
 
         for (c = 1; c <= 2 && *color; c++)
           {
@@ -482,9 +499,14 @@ process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct
         if (have_file)
           {
             if (file_string)
-              vfprintf_fail (formats[FMT_GENERIC], "file cannot be used as color string");
+              vfprintf_fail (formats[FMT_QUOTE], get_file_type (mode), color_string, "cannot be used as color string");
             else
-              vfprintf_fail (formats[FMT_GENERIC], "file must be preceeded by color string");
+              {
+                if (VALID_FILE_TYPE (mode))
+                  vfprintf_fail (formats[FMT_QUOTE], get_file_type (mode), color_string, "must be preceeded by color string");
+                else
+                  vfprintf_fail (formats[FMT_QUOTE], get_file_type (mode), color_string, "is not a valid file type");
+              }
           }
       }
 
@@ -597,13 +619,13 @@ process_file_arg (const char *file_string, const char **file, FILE **stream)
             int errno, ret;
 
             errno = 0;
-            ret = stat (file, &sb);
+            ret = lstat (file, &sb);
 
             if (ret == -1)
               vfprintf_fail (formats[FMT_FILE], file, strerror (errno));
 
-            if (!(S_ISREG (sb.st_mode) || S_ISLNK (sb.st_mode) || S_ISFIFO (sb.st_mode)))
-              vfprintf_fail (formats[FMT_FILE], file, "unrecognized file type");
+            if (!VALID_FILE_TYPE (sb.st_mode))
+              vfprintf_fail (formats[FMT_TYPE], file, "unrecognized type", get_file_type (sb.st_mode));
 
             errno = 0;
 
@@ -1002,6 +1024,27 @@ str_concat (const char *str1, const char *str2)
     return str;
 }
 
+static char *
+get_file_type (mode_t mode)
+{
+    if (S_ISREG (mode))
+      return "file";
+    else if (S_ISDIR (mode))
+      return "directory";
+    else if (S_ISCHR (mode))
+      return "character device";
+    else if (S_ISBLK (mode))
+      return "block device";
+    else if (S_ISFIFO (mode))
+      return "named pipe";
+    else if (S_ISLNK (mode))
+      return "symbolic link";
+    else if (S_ISSOCK (mode))
+      return "socket";
+    else
+      return "file";
+}
+
 static bool
 has_color_name (const char *str, const char *name)
 {