Use stat (lstat), not safe_stat (safe_lstat).
[platform/upstream/coreutils.git] / src / ls.c
1 /* `dir', `vdir' and `ls' directory listing programs for GNU.
2    Copyright (C) 1985, 1988, 1990, 1991, 1995 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17 \f
18 /* If the macro MULTI_COL is defined,
19    the multi-column format is the default regardless
20    of the type of output device.
21    This is for the `dir' program.
22
23    If the macro LONG_FORMAT is defined,
24    the long format is the default regardless of the
25    type of output device.
26    This is for the `vdir' program.
27
28    If neither is defined,
29    the output format depends on whether the output
30    device is a terminal.
31    This is for the `ls' program. */
32
33 /* Written by Richard Stallman and David MacKenzie. */
34
35 #ifdef _AIX
36  #pragma alloca
37 #endif
38
39 #include <config.h>
40 #include <sys/types.h>
41 #if !defined(_POSIX_SOURCE) || defined(_AIX)
42 #include <sys/ioctl.h>
43 #endif
44 #include <stdio.h>
45 #include <grp.h>
46 #include <pwd.h>
47 #include <getopt.h>
48 #if HAVE_LIMITS_H
49 /* limits.h must come before system.h because limits.h on some systems
50    undefs PATH_MAX, whereas system.h includes pathmax.h which sets
51    PATH_MAX.  */
52 #include <limits.h>
53 #endif
54
55 #include "system.h"
56 #include <fnmatch.h>
57
58 #include "obstack.h"
59 #include "ls.h"
60 #include "version.h"
61 #include "error.h"
62
63 #define obstack_chunk_alloc xmalloc
64 #define obstack_chunk_free free
65
66 #ifndef INT_MAX
67 #define INT_MAX 2147483647
68 #endif
69
70 /* Return an int indicating the result of comparing two longs. */
71 #if (INT_MAX <= 65535)
72 #define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
73 #else
74 #define longdiff(a, b) ((a) - (b))
75 #endif
76
77 /* The maximum number of digits required to print an inode number
78    in an unsigned format.  */
79 #ifndef INODE_DIGITS
80 #define INODE_DIGITS 7
81 #endif
82
83 #ifndef STDC_HEADERS
84 char *ctime ();
85 time_t time ();
86 void free ();
87 #endif
88
89 void mode_string ();
90
91 char *stpcpy ();
92 char *xstrdup ();
93 char *getgroup ();
94 char *getuser ();
95 char *xmalloc ();
96 char *xrealloc ();
97 int argmatch ();
98 void invalid_arg ();
99
100 static char *make_link_path ();
101 static int compare_atime ();
102 static int rev_cmp_atime ();
103 static int compare_ctime ();
104 static int rev_cmp_ctime ();
105 static int compare_mtime ();
106 static int rev_cmp_mtime ();
107 static int compare_size ();
108 static int rev_cmp_size ();
109 static int compare_name ();
110 static int rev_cmp_name ();
111 static int compare_extension ();
112 static int rev_cmp_extension ();
113 static int decode_switches ();
114 static void parse_ls_color ();
115 static int file_interesting ();
116 static int gobble_file ();
117 static int is_not_dot_or_dotdot ();
118 static int length_of_file_name_and_frills ();
119 static void add_ignore_pattern ();
120 static void attach ();
121 static void clear_files ();
122 static void extract_dirs_from_files ();
123 static void get_link_name ();
124 static void indent ();
125 static void print_current_files ();
126 static void print_dir ();
127 static void print_file_name_and_frills ();
128 static void print_horizontal ();
129 static void print_long_format ();
130 static void print_many_per_line ();
131 static void print_name_with_quoting ();
132 static void print_type_indicator ();
133 static void print_color_indicator ();
134 static void put_indicator ();
135 static void print_with_commas ();
136 static void queue_directory ();
137 static void sort_files ();
138 static void usage ();
139 \f
140 /* The name the program was run with, stripped of any leading path. */
141 char *program_name;
142
143 enum filetype
144   {
145     symbolic_link,
146     directory,
147     arg_directory,              /* Directory given as command line arg. */
148     normal                      /* All others. */
149   };
150
151 struct fileinfo
152   {
153     /* The file name. */
154     char *name;
155
156     struct stat stat;
157
158     /* For symbolic link, name of the file linked to, otherwise zero. */
159     char *linkname;
160
161     /* For symbolic link and long listing, st_mode of file linked to, otherwise
162        zero. */
163     unsigned int linkmode;
164
165     enum filetype filetype;
166   };
167
168 /* The table of files in the current directory:
169
170    `files' points to a vector of `struct fileinfo', one per file.
171    `nfiles' is the number of elements space has been allocated for.
172    `files_index' is the number actually in use.  */
173
174 /* Address of block containing the files that are described.  */
175
176 static struct fileinfo *files;
177
178 /* Length of block that `files' points to, measured in files.  */
179
180 static int nfiles;
181
182 /* Index of first unused in `files'.  */
183
184 static int files_index;
185
186 /* Record of one pending directory waiting to be listed.  */
187
188 struct pending
189   {
190     char *name;
191     /* If the directory is actually the file pointed to by a symbolic link we
192        were told to list, `realname' will contain the name of the symbolic
193        link, otherwise zero. */
194     char *realname;
195     struct pending *next;
196   };
197
198 static struct pending *pending_dirs;
199
200 /* Current time (seconds since 1970).  When we are printing a file's time,
201    include the year if it is more than 6 months before this time.  */
202
203 static time_t current_time;
204
205 /* The number of digits to use for block sizes.
206    4, or more if needed for bigger numbers.  */
207
208 static int block_size_size;
209 \f
210 /* Option flags */
211
212 /* long_format for lots of info, one per line.
213    one_per_line for just names, one per line.
214    many_per_line for just names, many per line, sorted vertically.
215    horizontal for just names, many per line, sorted horizontally.
216    with_commas for just names, many per line, separated by commas.
217
218    -l, -1, -C, -x and -m control this parameter.  */
219
220 enum format
221   {
222     long_format,                /* -l */
223     one_per_line,               /* -1 */
224     many_per_line,              /* -C */
225     horizontal,                 /* -x */
226     with_commas                 /* -m */
227   };
228
229 static enum format format;
230
231 /* Type of time to print or sort by.  Controlled by -c and -u.  */
232
233 enum time_type
234   {
235     time_mtime,                 /* default */
236     time_ctime,                 /* -c */
237     time_atime                  /* -u */
238   };
239
240 static enum time_type time_type;
241
242 /* print the full time, otherwise the standard unix heuristics. */
243
244 int full_time;
245
246 /* The file characteristic to sort by.  Controlled by -t, -S, -U, -X. */
247
248 enum sort_type
249   {
250     sort_none,                  /* -U */
251     sort_name,                  /* default */
252     sort_extension,             /* -X */
253     sort_time,                  /* -t */
254     sort_size                   /* -S */
255   };
256
257 static enum sort_type sort_type;
258
259 /* Direction of sort.
260    0 means highest first if numeric,
261    lowest first if alphabetic;
262    these are the defaults.
263    1 means the opposite order in each case.  -r  */
264
265 static int sort_reverse;
266
267 /* Nonzero means to NOT display group information.  -G  */
268
269 int inhibit_group;
270
271 /* Nonzero means print the user and group id's as numbers rather
272    than as names.  -n  */
273
274 static int numeric_users;
275
276 /* Nonzero means mention the size in 512 byte blocks of each file.  -s  */
277
278 static int print_block_size;
279
280 /* Nonzero means show file sizes in kilobytes instead of blocks
281    (the size of which is system-dependent).  -k */
282
283 static int kilobyte_blocks;
284
285 /* Precede each line of long output (per file) with a string like `m,n:'
286    where M is the number of characters after the `:' and before the
287    filename and N is the length of the filename.  Using this format,
288    Emacs' dired mode starts up twice as fast, and can handle all
289    strange characters in file names.  */
290 static int dired;
291
292 /* none means don't mention the type of files.
293    all means mention the types of all files.
294    not_programs means do so except for executables.
295
296    Controlled by -F and -p.  */
297
298 enum indicator_style
299   {
300     none,                       /* default */
301     all,                        /* -F */
302     not_programs                /* -p */
303   };
304
305 static enum indicator_style indicator_style;
306
307 /* Nonzero means use colors to mark types.  Also define the different
308    colors as well as the stuff for the LS_COLORS environment variable.
309    The LS_COLORS variable is now in a termcap-like format.  -o or
310    --color-if-tty. */
311
312 static int print_with_color;
313
314 enum color_type
315   {
316     color_no,                   /* 0: default or --color=no */
317     color_yes,                  /* 1: -o or --color=yes */
318     color_if_tty                /* 2: --color=tty */
319   };
320
321 /* Note that color_no and color_yes equals boolean values; they will
322    be assigned to print_with_color which is a boolean variable */
323
324 #define MAXCOLORLEN  16         /* Max # of characters in a color sequence */
325
326 enum indicator_no
327   {
328     C_LEFT, C_RIGHT, C_END, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
329     C_BLK, C_CHR, C_EXEC
330   };
331
332 const char *const indicator_name[] =
333 {
334   "lc", "rc", "ec", "fi", "di", "ln", "pi", "so", "bd", "cd", "ex", NULL
335 };
336
337 struct indicator_type
338   {
339     int len;
340     char string[MAXCOLORLEN];
341   };
342
343 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
344
345 static struct indicator_type color_indicator[] =
346 {
347   {LEN_STR_PAIR ("\033[")},     /* lc: Left of color sequence */
348   {LEN_STR_PAIR ("m")},         /* rc: Right of color sequence */
349   {LEN_STR_PAIR ("\033[0m")},   /* ec: End color */
350   {LEN_STR_PAIR ("0")},         /* fi: File: default */
351   {LEN_STR_PAIR ("32")},        /* di: Directory: green */
352   {LEN_STR_PAIR ("36")},        /* ln: Symlink: cyan */
353   {LEN_STR_PAIR ("31")},        /* pi: Pipe: red */
354   {LEN_STR_PAIR ("33")},        /* so: Socket: yellow/brown */
355   {LEN_STR_PAIR ("44;37")},     /* bd: Block device: white on blue */
356   {LEN_STR_PAIR ("44;37")},     /* cd: Char device: white on blue */
357   {LEN_STR_PAIR ("35")},        /* ex: Executable: purple */
358 };
359
360 /* Nonzero means print using ISO 8859 characters.  The default is specified
361    here as well.  -8 enables, -7 disables.  */
362
363 static int print_iso8859;
364 #ifndef DEFAULT_ISO8859
365 #define DEFAULT_ISO8859  1
366 #endif
367
368 /* Nonzero means mention the inode number of each file.  -i  */
369
370 static int print_inode;
371
372 /* Nonzero means when a symbolic link is found, display info on
373    the file linked to.  -L  */
374
375 static int trace_links;
376
377 /* Nonzero means when a directory is found, display info on its
378    contents.  -R  */
379
380 static int trace_dirs;
381
382 /* Nonzero means when an argument is a directory name, display info
383    on it itself.  -d  */
384
385 static int immediate_dirs;
386
387 /* Nonzero means don't omit files whose names start with `.'.  -A */
388
389 static int all_files;
390
391 /* Nonzero means don't omit files `.' and `..'
392    This flag implies `all_files'.  -a  */
393
394 static int really_all_files;
395
396 /* A linked list of shell-style globbing patterns.  If a non-argument
397    file name matches any of these patterns, it is omitted.
398    Controlled by -I.  Multiple -I options accumulate.
399    The -B option adds `*~' and `.*~' to this list.  */
400
401 struct ignore_pattern
402   {
403     char *pattern;
404     struct ignore_pattern *next;
405   };
406
407 static struct ignore_pattern *ignore_patterns;
408
409 /* Nonzero means quote nongraphic chars in file names.  -b  */
410
411 static int quote_funny_chars;
412
413 /* Nonzero means output nongraphic chars in file names as `?'.  -q  */
414
415 static int qmark_funny_chars;
416
417 /* Nonzero means output each file name using C syntax for a string.
418    Always accompanied by `quote_funny_chars'.
419    This mode, together with -x or -C or -m,
420    and without such frills as -F or -s,
421    is guaranteed to make it possible for a program receiving
422    the output to tell exactly what file names are present.  -Q  */
423
424 static int quote_as_string;
425
426 /* The number of chars per hardware tab stop.  -T */
427 static int tabsize;
428
429 /* Nonzero means we are listing the working directory because no
430    non-option arguments were given. */
431
432 static int dir_defaulted;
433
434 /* Nonzero means print each directory name before listing it. */
435
436 static int print_dir_name;
437
438 /* The line length to use for breaking lines in many-per-line format.
439    Can be set with -w.  */
440
441 static int line_length;
442
443 /* If nonzero, the file listing format requires that stat be called on
444    each file. */
445
446 static int format_needs_stat;
447
448 /* The exit status to use if we don't get any fatal errors. */
449
450 static int exit_status;
451
452 /* If non-zero, display usage information and exit.  */
453 static int show_help;
454
455 /* If non-zero, print the version on standard output and exit.  */
456 static int show_version;
457
458 static struct option const long_options[] =
459 {
460   {"all", no_argument, 0, 'a'},
461   {"escape", no_argument, 0, 'b'},
462   {"directory", no_argument, 0, 'd'},
463   {"dired", no_argument, 0, 'D'},
464   {"full-time", no_argument, &full_time, 1},
465   {"inode", no_argument, 0, 'i'},
466   {"kilobytes", no_argument, 0, 'k'},
467   {"numeric-uid-gid", no_argument, 0, 'n'},
468   {"no-group", no_argument, 0, 'G'},
469   {"hide-control-chars", no_argument, 0, 'q'},
470   {"reverse", no_argument, 0, 'r'},
471   {"size", no_argument, 0, 's'},
472   {"width", required_argument, 0, 'w'},
473   {"almost-all", no_argument, 0, 'A'},
474   {"ignore-backups", no_argument, 0, 'B'},
475   {"classify", no_argument, 0, 'F'},
476   {"file-type", no_argument, 0, 'F'},
477   {"ignore", required_argument, 0, 'I'},
478   {"dereference", no_argument, 0, 'L'},
479   {"literal", no_argument, 0, 'N'},
480   {"quote-name", no_argument, 0, 'Q'},
481   {"recursive", no_argument, 0, 'R'},
482   {"format", required_argument, 0, 12},
483   {"sort", required_argument, 0, 10},
484   {"tabsize", required_argument, 0, 'T'},
485   {"time", required_argument, 0, 11},
486   {"help", no_argument, &show_help, 1},
487   {"version", no_argument, &show_version, 1},
488   {"color", optional_argument, 0, 'o'},
489   {"colour", optional_argument, 0, 'o'},
490   {"7bit", no_argument, 0, '7'},
491   {"8bit", no_argument, 0, '8'},
492   {0, 0, 0, 0}
493 };
494
495 static char const *const format_args[] =
496 {
497   "verbose", "long", "commas", "horizontal", "across",
498   "vertical", "single-column", 0
499 };
500
501 static enum format const formats[] =
502 {
503   long_format, long_format, with_commas, horizontal, horizontal,
504   many_per_line, one_per_line
505 };
506
507 static char const *const sort_args[] =
508 {
509   "none", "time", "size", "extension", 0
510 };
511
512 static enum sort_type const sort_types[] =
513 {
514   sort_none, sort_time, sort_size, sort_extension
515 };
516
517 static char const *const time_args[] =
518 {
519   "atime", "access", "use", "ctime", "status", 0
520 };
521
522 /* This zero-based index is used solely with the --dired option.
523    When that option is in effect, this counter is incremented for each
524    character of output generated by this program so that the beginning
525    and ending indices (in that output) of every file name can be recorded
526    and later output themselves.  */
527 static size_t dired_pos;
528
529 #define PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
530
531 /* Write S to STREAM and increment DIRED_POS by S_LEN.  */
532 #define FPUTS(s, stream, s_len) \
533     do {fputs ((s), (stream)); dired_pos += s_len;} while (0)
534
535 /* Like FPUTS, but for use when S is a literal string.  */
536 #define FPUTS_LITERAL(s, stream) \
537     do {fputs ((s), (stream)); dired_pos += sizeof((s)) - 1;} while (0)
538
539 #define DIRED_INDENT()                                                  \
540     do                                                                  \
541       {                                                                 \
542         /* FIXME: remove the `&& format == long_format' clause.  */     \
543         if (dired && format == long_format)                             \
544           FPUTS_LITERAL ("  ", stdout);                                 \
545       }                                                                 \
546     while (0)
547
548 /* With --dired, store pairs of beginning and ending indices of filenames.  */
549 static struct obstack dired_obstack;
550
551 /* With --dired and --recursive, store pairs of beginning and ending
552    indices of directory names.  */
553 static struct obstack subdired_obstack;
554
555 /* Save the current index on the specified obstack, OBS.  */
556 #define PUSH_CURRENT_DIRED_POS(obs)                                     \
557   do                                                                    \
558     {                                                                   \
559       /* FIXME: remove the `&& format == long_format' clause.  */       \
560       if (dired && format == long_format)                               \
561         obstack_grow ((obs), &dired_pos, sizeof (dired_pos));           \
562     }                                                                   \
563   while (0)
564
565 static enum time_type const time_types[] =
566 {
567   time_atime, time_atime, time_atime, time_ctime, time_ctime
568 };
569
570 static char const *const color_args[] =
571 {
572   /* Note: "no" is a prefix of "none" so we don't include it */
573   "yes", "force", "none", "tty", "if-tty"
574 };
575
576 static enum color_type const color_types[] =
577 {
578   color_yes, color_yes, color_no, color_if_tty, color_if_tty
579 };
580 \f
581 /* Write to standard output the string PREFIX followed by a space-separated
582    list of the integers stored in OS all on one line.  */
583
584 static void
585 dired_dump_obstack (prefix, os)
586      const char *prefix;
587      struct obstack *os;
588 {
589   int i, n_pos;
590   size_t *pos;
591
592   fputs (prefix, stdout);
593   n_pos = obstack_object_size (os) / sizeof (size_t);
594   pos = (size_t *) obstack_finish (os);
595   for (i = 0; i < n_pos; i++)
596     printf (" %d", (int) pos[i]);
597   fputs ("\n", stdout);
598 }
599
600 void
601 main (argc, argv)
602      int argc;
603      char **argv;
604 {
605   register int i;
606   register struct pending *thispend;
607
608   exit_status = 0;
609   dir_defaulted = 1;
610   print_dir_name = 1;
611   pending_dirs = 0;
612   current_time = time ((time_t *) 0);
613
614   program_name = argv[0];
615   i = decode_switches (argc, argv);
616
617   if (show_version)
618     {
619       printf ("%s\n", version_string);
620       exit (0);
621     }
622
623   if (show_help)
624     usage (0);
625
626   format_needs_stat = sort_type == sort_time || sort_type == sort_size
627     || format == long_format
628     || trace_links || trace_dirs || indicator_style != none
629     || print_block_size || print_inode || print_with_color;
630
631   if (dired && format == long_format)
632     {
633       obstack_init (&dired_obstack);
634       if (trace_dirs)
635         obstack_init (&subdired_obstack);
636     }
637
638   nfiles = 100;
639   files = (struct fileinfo *) xmalloc (sizeof (struct fileinfo) * nfiles);
640   files_index = 0;
641
642   clear_files ();
643
644   if (i < argc)
645     dir_defaulted = 0;
646   for (; i < argc; i++)
647     gobble_file (argv[i], 1, "");
648
649   if (dir_defaulted)
650     {
651       if (immediate_dirs)
652         gobble_file (".", 1, "");
653       else
654         queue_directory (".", 0);
655     }
656
657   if (files_index)
658     {
659       sort_files ();
660       if (!immediate_dirs)
661         extract_dirs_from_files ("", 0);
662       /* `files_index' might be zero now.  */
663     }
664   if (files_index)
665     {
666       print_current_files ();
667       if (pending_dirs)
668         PUTCHAR ('\n');
669     }
670   else if (pending_dirs && pending_dirs->next == 0)
671     print_dir_name = 0;
672
673   while (pending_dirs)
674     {
675       thispend = pending_dirs;
676       pending_dirs = pending_dirs->next;
677       print_dir (thispend->name, thispend->realname);
678       free (thispend->name);
679       if (thispend->realname)
680         free (thispend->realname);
681       free (thispend);
682       print_dir_name = 1;
683     }
684
685   if (dired && format == long_format)
686     {
687       /* No need to free these since we're about to exit.  */
688       dired_dump_obstack ("//DIRED//", &dired_obstack);
689       if (trace_dirs)
690         dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
691     }
692
693   exit (exit_status);
694 }
695 \f
696 /* Set all the option flags according to the switches specified.
697    Return the index of the first non-option argument.  */
698
699 static int
700 decode_switches (argc, argv)
701      int argc;
702      char **argv;
703 {
704   register char *p;
705   int c;
706   int i;
707
708   qmark_funny_chars = 0;
709   quote_funny_chars = 0;
710
711   /* initialize all switches to default settings */
712
713   switch (ls_mode)
714     {
715     case LS_MULTI_COL:
716       /* This is for the `dir' program.  */
717       format = many_per_line;
718       quote_funny_chars = 1;
719       break;
720
721     case LS_LONG_FORMAT:
722       /* This is for the `vdir' program.  */
723       format = long_format;
724       quote_funny_chars = 1;
725       break;
726
727     case LS_LS:
728       /* This is for the `ls' program.  */
729       if (isatty (1))
730         {
731           format = many_per_line;
732           qmark_funny_chars = 1;
733         }
734       else
735         {
736           format = one_per_line;
737           qmark_funny_chars = 0;
738         }
739       break;
740
741     default:
742       abort ();
743     }
744
745   time_type = time_mtime;
746   full_time = 0;
747   sort_type = sort_name;
748   sort_reverse = 0;
749   numeric_users = 0;
750   print_block_size = 0;
751   kilobyte_blocks = getenv ("POSIXLY_CORRECT") == 0;
752   indicator_style = none;
753   print_inode = 0;
754   trace_links = 0;
755   trace_dirs = 0;
756   immediate_dirs = 0;
757   all_files = 0;
758   really_all_files = 0;
759   ignore_patterns = 0;
760   quote_as_string = 0;
761   print_with_color = 0;
762   print_iso8859 = DEFAULT_ISO8859;
763
764   p = getenv ("COLUMNS");
765   line_length = p ? atoi (p) : 80;
766
767 #ifdef TIOCGWINSZ
768   {
769     struct winsize ws;
770
771     if (ioctl (1, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
772       line_length = ws.ws_col;
773   }
774 #endif
775
776   /* FIXME: reference TABSIZE iff !posix_pedantic.  */
777   p = getenv ("TABSIZE");
778   /* FIXME: use strtol here!  */
779   tabsize = p ? atoi (p) : 8;
780   if (tabsize < 1)
781     {
782       error (0, 0,
783              "ignoring invalid tab size in enironment variable TABSIZE: %s",
784              optarg);
785       tabsize = 8;
786     }
787
788   while ((c = getopt_long (argc, argv,
789                            "abcdfgiklmnopqrstuw:xABCDFGI:LNQRST:UX178",
790                            long_options, (int *) 0)) != EOF)
791     {
792       switch (c)
793         {
794         case 0:
795           break;
796
797         case 'a':
798           all_files = 1;
799           really_all_files = 1;
800           break;
801
802         case 'b':
803           quote_funny_chars = 1;
804           qmark_funny_chars = 0;
805           break;
806
807         case 'c':
808           time_type = time_ctime;
809           break;
810
811         case 'd':
812           immediate_dirs = 1;
813           break;
814
815         case 'f':
816           /* Same as enabling -a -U and disabling -l -s.  */
817           all_files = 1;
818           really_all_files = 1;
819           sort_type = sort_none;
820           /* disable -l */
821           if (format == long_format)
822             format = (isatty (1) ? many_per_line : one_per_line);
823           print_block_size = 0; /* disable -s */
824           break;
825
826         case 'g':
827           /* No effect.  For BSD compatibility. */
828           break;
829
830         case 'i':
831           print_inode = 1;
832           break;
833
834         case 'k':
835           kilobyte_blocks = 1;
836           break;
837
838         case 'l':
839           format = long_format;
840           break;
841
842         case 'm':
843           format = with_commas;
844           break;
845
846         case 'n':
847           numeric_users = 1;
848           break;
849
850         case 'o':
851           if (optarg)
852             {
853               i = argmatch (optarg, color_args);
854               if (i < 0)
855                 {
856                   invalid_arg ("colorization criterion", optarg, i);
857                   usage (1);
858                 }
859               i = color_types[i];
860             }
861           else
862             i = color_yes;      /* -o or --color -> do colorize */
863
864           if (i == color_if_tty)
865             print_with_color = isatty (1) ? 1 : 0;
866           else
867             print_with_color = i;
868
869           if (print_with_color)
870             {
871               /* Don't use TAB characters in output.  Some terminal
872                  emulators can't handle the combination of tabs and
873                  color codes on the same line.  */
874               tabsize = line_length;
875             }
876           break;
877
878         case 'p':
879           indicator_style = not_programs;
880           break;
881
882         case 'q':
883           qmark_funny_chars = 1;
884           quote_funny_chars = 0;
885           break;
886
887         case 'r':
888           sort_reverse = 1;
889           break;
890
891         case 's':
892           print_block_size = 1;
893           break;
894
895         case 't':
896           sort_type = sort_time;
897           break;
898
899         case 'u':
900           time_type = time_atime;
901           break;
902
903         case 'w':
904           line_length = atoi (optarg);
905           if (line_length < 1)
906             error (1, 0, "invalid line width: %s", optarg);
907           break;
908
909         case 'x':
910           format = horizontal;
911           break;
912
913         case 'A':
914           all_files = 1;
915           break;
916
917         case 'B':
918           add_ignore_pattern ("*~");
919           add_ignore_pattern (".*~");
920           break;
921
922         case 'C':
923           format = many_per_line;
924           break;
925
926         case 'D':
927           dired = 1;
928           break;
929
930         case 'F':
931           indicator_style = all;
932           break;
933
934         case 'G':               /* inhibit display of group info */
935           inhibit_group = 1;
936           break;
937
938         case 'I':
939           add_ignore_pattern (optarg);
940           break;
941
942         case 'L':
943           trace_links = 1;
944           break;
945
946         case 'N':
947           quote_funny_chars = 0;
948           qmark_funny_chars = 0;
949           break;
950
951         case 'Q':
952           quote_as_string = 1;
953           quote_funny_chars = 1;
954           qmark_funny_chars = 0;
955           break;
956
957         case 'R':
958           trace_dirs = 1;
959           break;
960
961         case 'S':
962           sort_type = sort_size;
963           break;
964
965         case 'T':
966           tabsize = atoi (optarg);
967           if (tabsize < 1)
968             error (1, 0, "invalid tab size: %s", optarg);
969           break;
970
971         case 'U':
972           sort_type = sort_none;
973           break;
974
975         case 'X':
976           sort_type = sort_extension;
977           break;
978
979         case '1':
980           format = one_per_line;
981           break;
982
983         case '7':
984           print_iso8859 = 0;
985           break;
986
987         case '8':
988           print_iso8859 = 1;
989           break;
990
991         case 10:                /* --sort */
992           i = argmatch (optarg, sort_args);
993           if (i < 0)
994             {
995               invalid_arg ("sort type", optarg, i);
996               usage (1);
997             }
998           sort_type = sort_types[i];
999           break;
1000
1001         case 11:                /* --time */
1002           i = argmatch (optarg, time_args);
1003           if (i < 0)
1004             {
1005               invalid_arg ("time type", optarg, i);
1006               usage (1);
1007             }
1008           time_type = time_types[i];
1009           break;
1010
1011         case 12:                /* --format */
1012           i = argmatch (optarg, format_args);
1013           if (i < 0)
1014             {
1015               invalid_arg ("format type", optarg, i);
1016               usage (1);
1017             }
1018           format = formats[i];
1019           break;
1020
1021         default:
1022           usage (1);
1023         }
1024     }
1025
1026   if (print_with_color)
1027     {
1028       parse_ls_color ();
1029     }
1030
1031   return optind;
1032 }
1033 \f
1034 /* Parse the LS_COLORS/LS_COLOURS variable */
1035
1036 static void
1037 parse_ls_color ()
1038 {
1039   register char *p;             /* Pointer to character being parsed */
1040   char *whichvar;               /* LS_COLORS or LS_COLOURS? */
1041   int state;                    /* State of parser */
1042   int ind_no;                   /* Indicator number */
1043   int ccount;                   /* Character count */
1044   int num;                      /* Escape char numeral */
1045   char label[3] = "??";         /* Indicator label */
1046
1047   if ((p = getenv (whichvar = "LS_COLORS")) ||
1048       (p = getenv (whichvar = "LS_COLOURS")))
1049     {
1050       state = 1;
1051       while (state > 0)
1052         {
1053           switch (state)
1054             {
1055             case 1:             /* First label character */
1056               if (*p)
1057                 {
1058                   label[0] = *(p++);
1059                   state = 2;
1060                 }
1061               else
1062                 state = 0;      /* Done */
1063               break;
1064
1065             case 2:             /* Second label character */
1066               if (*p)
1067                 {
1068                   label[1] = *(p++);
1069                   state = 3;
1070                 }
1071               else
1072                 state = -1;     /* Error */
1073               break;
1074
1075             case 3:             /* Should be equal sign */
1076               if (*(p++) != '=')
1077                 state = -1;     /* Error state */
1078               else
1079                 {
1080                   ind_no = 0;
1081                   state = -1;   /* In case we fail */
1082                   while (indicator_name[ind_no] != NULL)
1083                     {
1084                       if (strcmp (label, indicator_name[ind_no]) == 0)
1085                         {
1086                           state = 4;    /* We found it */
1087                           ccount = 0;   /* Nothing stored yet */
1088                           break;
1089                         }
1090                       else
1091                         ind_no++;
1092                     }
1093                 }
1094               break;
1095
1096             case 4:             /* Character to store */
1097               switch (*p)
1098                 {
1099                 case ':':
1100                   color_indicator[ind_no].len = ccount;
1101                   state = 1;
1102                   break;
1103                 case '\\':
1104                   /* The escape sequence will always generate a character,
1105                      so enter error state if the buffer is full */
1106                   state = (ccount >= MAXCOLORLEN) ? -1 : 5;
1107                   break;
1108                 case '^':
1109                   /* Control character in the ^X notation */
1110                   state = (ccount >= MAXCOLORLEN) ? -1 : 8;
1111                   break;
1112                 case '\0':
1113                   color_indicator[ind_no].len = ccount;
1114                   state = 0;    /* Done */
1115                   break;
1116                 default:
1117                   if (ccount >= MAXCOLORLEN)
1118                     state = -1; /* Too long */
1119                   else
1120                     color_indicator[ind_no].string[ccount++] = *p;
1121                 }
1122               p++;
1123               break;
1124
1125             case 5:             /* Escape character */
1126               num = -1;
1127               switch (*p)
1128                 {
1129                 case '0':
1130                 case '1':
1131                 case '2':
1132                 case '3':
1133                 case '4':
1134                 case '5':
1135                 case '6':
1136                 case '7':
1137                   state = 6;    /* Octal numeral */
1138                   num = *p - '0';
1139                   break;
1140                 case 'x':
1141                 case 'X':
1142                   state = 7;    /* Hex numeral */
1143                   num = 0;
1144                   break;
1145                 case 'a':       /* Bell */
1146                   num = 7;
1147                   break;
1148                 case 'b':       /* Backspace */
1149                   num = '\b';
1150                   break;
1151                 case 'e':       /* Escape */
1152                   num = 27;
1153                   break;
1154                 case 'f':       /* Formfeed */
1155                   num = '\f';
1156                   break;
1157                 case 'n':       /* Newline */
1158                   num = '\n';
1159                   break;
1160                 case 'r':       /* Return */
1161                   num = '\r';
1162                   break;
1163                 case 't':       /* Tab */
1164                   num = '\t';
1165                   break;
1166                 case 'v':       /* Vtab */
1167                   num = '\v';
1168                   break;
1169                 case '?':       /* Delete */
1170                   num = 127;
1171                   break;
1172                 case '\0':      /* End of string */
1173                   state = -1;   /* Error */
1174                   break;
1175                 default:        /* Escaped character */
1176                   num = *p;
1177                   break;
1178                 }
1179               if (state == 5)
1180                 {
1181                   color_indicator[ind_no].string[ccount++] = num;
1182                   state = 4;
1183                 }
1184               p++;
1185               break;
1186
1187             case 6:             /* Octal numeral */
1188               switch (*p)
1189                 {
1190                 case ':':
1191                 case '\0':
1192                   color_indicator[ind_no].string[ccount++] = num;
1193                   color_indicator[ind_no].len = ccount;
1194                   state = (*(p++) == ':') ? 1 : 0;
1195                   p++;
1196                   break;
1197                 case '0':
1198                 case '1':
1199                 case '2':
1200                 case '3':
1201                 case '4':
1202                 case '5':
1203                 case '6':
1204                 case '7':
1205                   num = (num << 3) + (*(p++) - '0');
1206                   break;
1207                 default:
1208                   color_indicator[ind_no].string[ccount++] = num;
1209                   state = 4;
1210                   break;
1211                 }
1212               break;
1213
1214             case 7:             /* Hex numeral */
1215               switch (*p)
1216                 {
1217                 case ':':
1218                 case '\0':
1219                   color_indicator[ind_no].string[ccount++] = num;
1220                   color_indicator[ind_no].len = ccount;
1221                   state = (*(p++) == ':') ? 1 : 0;
1222                   break;
1223                 case '0':
1224                 case '1':
1225                 case '2':
1226                 case '3':
1227                 case '4':
1228                 case '5':
1229                 case '6':
1230                 case '7':
1231                 case '8':
1232                 case '9':
1233                   num = (num << 4) + (*(p++) - '0');
1234                   break;
1235                 case 'A':
1236                 case 'B':
1237                 case 'C':
1238                 case 'D':
1239                 case 'E':
1240                 case 'F':
1241                   num = (num << 4) + (*(p++) - 'A' + 10);
1242                   break;
1243                 case 'a':
1244                 case 'b':
1245                 case 'c':
1246                 case 'd':
1247                 case 'e':
1248                 case 'f':
1249                   num = (num << 4) + (*(p++) - 'a' + 10);
1250                   break;
1251                 default:
1252                   color_indicator[ind_no].string[ccount++] = num;
1253                   state = 4;
1254                   break;
1255                 }
1256               break;
1257
1258             case 8:             /* ^ notation */
1259               state = 4;        /* Usually the next state */
1260               if (*p >= '@' && *p <= '~')
1261                 color_indicator[ind_no].string[ccount++] = *p & 037;
1262               else if (*p == '?')
1263                 color_indicator[ind_no].string[ccount++] = 127;
1264               else
1265                 state = -1;     /* Error */
1266               p++;
1267               break;
1268             }
1269         }
1270
1271       if (state < 0)
1272         {
1273           error (0, 0, "bad %s variable\n", whichvar);
1274           print_with_color = 0;
1275         }
1276     }
1277 }
1278 \f
1279 /* Request that the directory named `name' have its contents listed later.
1280    If `realname' is nonzero, it will be used instead of `name' when the
1281    directory name is printed.  This allows symbolic links to directories
1282    to be treated as regular directories but still be listed under their
1283    real names. */
1284
1285 static void
1286 queue_directory (name, realname)
1287      char *name;
1288      char *realname;
1289 {
1290   struct pending *new;
1291
1292   new = (struct pending *) xmalloc (sizeof (struct pending));
1293   new->next = pending_dirs;
1294   pending_dirs = new;
1295   new->name = xstrdup (name);
1296   if (realname)
1297     new->realname = xstrdup (realname);
1298   else
1299     new->realname = 0;
1300 }
1301
1302 /* Read directory `name', and list the files in it.
1303    If `realname' is nonzero, print its name instead of `name';
1304    this is used for symbolic links to directories. */
1305
1306 static void
1307 print_dir (name, realname)
1308      const char *name;
1309      const char *realname;
1310 {
1311   register DIR *reading;
1312   register struct dirent *next;
1313   register int total_blocks = 0;
1314
1315   errno = 0;
1316   reading = opendir (name);
1317   if (!reading)
1318     {
1319       error (0, errno, "%s", name);
1320       exit_status = 1;
1321       return;
1322     }
1323
1324   /* Read the directory entries, and insert the subfiles into the `files'
1325      table.  */
1326
1327   clear_files ();
1328
1329   while ((next = readdir (reading)) != NULL)
1330     if (file_interesting (next))
1331       total_blocks += gobble_file (next->d_name, 0, name);
1332
1333   if (CLOSEDIR (reading))
1334     {
1335       error (0, errno, "%s", name);
1336       exit_status = 1;
1337       /* Don't return; print whatever we got. */
1338     }
1339
1340   /* Sort the directory contents.  */
1341   sort_files ();
1342
1343   /* If any member files are subdirectories, perhaps they should have their
1344      contents listed rather than being mentioned here as files.  */
1345
1346   if (trace_dirs)
1347     extract_dirs_from_files (name, 1);
1348
1349   if (print_dir_name)
1350     {
1351       const char *dir;
1352
1353       DIRED_INDENT ();
1354       dir = (realname ? realname : name);
1355       PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1356       FPUTS (dir, stdout, strlen (dir));
1357       PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1358       FPUTS_LITERAL (":\n", stdout);
1359     }
1360
1361   if (format == long_format || print_block_size)
1362     {
1363       char buf[6 + 20 + 1 + 1];
1364
1365       DIRED_INDENT ();
1366       sprintf (buf, "total %u\n", total_blocks);
1367       FPUTS (buf, stdout, strlen (buf));
1368     }
1369
1370   if (files_index)
1371     print_current_files ();
1372
1373   if (pending_dirs)
1374     PUTCHAR ('\n');
1375 }
1376 \f
1377 /* Add `pattern' to the list of patterns for which files that match are
1378    not listed.  */
1379
1380 static void
1381 add_ignore_pattern (pattern)
1382      char *pattern;
1383 {
1384   register struct ignore_pattern *ignore;
1385
1386   ignore = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
1387   ignore->pattern = pattern;
1388   /* Add it to the head of the linked list. */
1389   ignore->next = ignore_patterns;
1390   ignore_patterns = ignore;
1391 }
1392
1393 /* Return nonzero if the file in `next' should be listed. */
1394
1395 static int
1396 file_interesting (next)
1397      register struct dirent *next;
1398 {
1399   register struct ignore_pattern *ignore;
1400
1401   for (ignore = ignore_patterns; ignore; ignore = ignore->next)
1402     if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
1403       return 0;
1404
1405   if (really_all_files
1406       || next->d_name[0] != '.'
1407       || (all_files
1408           && next->d_name[1] != '\0'
1409           && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
1410     return 1;
1411
1412   return 0;
1413 }
1414 \f
1415 /* Enter and remove entries in the table `files'.  */
1416
1417 /* Empty the table of files. */
1418
1419 static void
1420 clear_files ()
1421 {
1422   register int i;
1423
1424   for (i = 0; i < files_index; i++)
1425     {
1426       free (files[i].name);
1427       if (files[i].linkname)
1428         free (files[i].linkname);
1429     }
1430
1431   files_index = 0;
1432   block_size_size = 4;
1433 }
1434
1435 /* Add a file to the current table of files.
1436    Verify that the file exists, and print an error message if it does not.
1437    Return the number of blocks that the file occupies.  */
1438
1439 static int
1440 gobble_file (name, explicit_arg, dirname)
1441      char *name;
1442      int explicit_arg;
1443      char *dirname;
1444 {
1445   register int blocks;
1446   register int val;
1447   register char *path;
1448
1449   if (files_index == nfiles)
1450     {
1451       nfiles *= 2;
1452       files = (struct fileinfo *) xrealloc (files, sizeof (*files) * nfiles);
1453     }
1454
1455   files[files_index].linkname = 0;
1456   files[files_index].linkmode = 0;
1457
1458   if (explicit_arg || format_needs_stat)
1459     {
1460       /* `path' is the absolute pathname of this file. */
1461
1462       if (name[0] == '/' || dirname[0] == 0)
1463         path = name;
1464       else
1465         {
1466           path = (char *) alloca (strlen (name) + strlen (dirname) + 2);
1467           attach (path, dirname, name);
1468         }
1469
1470       if (trace_links)
1471         {
1472           val = stat (path, &files[files_index].stat);
1473           if (val < 0)
1474             /* Perhaps a symbolically-linked to file doesn't exist; stat
1475                the link instead. */
1476             val = lstat (path, &files[files_index].stat);
1477         }
1478       else
1479         val = lstat (path, &files[files_index].stat);
1480       if (val < 0)
1481         {
1482           error (0, errno, "%s", path);
1483           exit_status = 1;
1484           return 0;
1485         }
1486
1487 #ifdef S_ISLNK
1488       if (S_ISLNK (files[files_index].stat.st_mode)
1489           && (explicit_arg || format == long_format))
1490         {
1491           char *linkpath;
1492           struct stat linkstats;
1493
1494           get_link_name (path, &files[files_index]);
1495           linkpath = make_link_path (path, files[files_index].linkname);
1496
1497           /* Avoid following symbolic links when possible, ie, when
1498              they won't be traced and when no indicator is needed. */
1499           if (linkpath
1500               && ((explicit_arg && format != long_format)
1501                   || indicator_style != none || print_with_color)
1502               && stat (linkpath, &linkstats) == 0)
1503             {
1504               /* Symbolic links to directories that are mentioned on the
1505                  command line are automatically traced if not being
1506                  listed as files.  */
1507               if (explicit_arg && format != long_format
1508                   && S_ISDIR (linkstats.st_mode))
1509                 {
1510                   /* Substitute the linked-to directory's name, but
1511                      save the real name in `linkname' for printing.  */
1512                   if (!immediate_dirs)
1513                     {
1514                       char *tempname = name;
1515                       name = linkpath;
1516                       linkpath = files[files_index].linkname;
1517                       files[files_index].linkname = tempname;
1518                     }
1519                   files[files_index].stat = linkstats;
1520                 }
1521               else
1522                 /* Get the linked-to file's mode for the filetype indicator
1523                    in long listings.  */
1524                 files[files_index].linkmode = linkstats.st_mode;
1525             }
1526           if (linkpath)
1527             free (linkpath);
1528         }
1529 #endif
1530
1531 #ifdef S_ISLNK
1532       if (S_ISLNK (files[files_index].stat.st_mode))
1533         files[files_index].filetype = symbolic_link;
1534       else
1535 #endif
1536       if (S_ISDIR (files[files_index].stat.st_mode))
1537         {
1538           if (explicit_arg && !immediate_dirs)
1539             files[files_index].filetype = arg_directory;
1540           else
1541             files[files_index].filetype = directory;
1542         }
1543       else
1544         files[files_index].filetype = normal;
1545
1546       blocks = convert_blocks (ST_NBLOCKS (files[files_index].stat),
1547                                kilobyte_blocks);
1548       if (blocks >= 10000 && block_size_size < 5)
1549         block_size_size = 5;
1550       if (blocks >= 100000 && block_size_size < 6)
1551         block_size_size = 6;
1552       if (blocks >= 1000000 && block_size_size < 7)
1553         block_size_size = 7;
1554     }
1555   else
1556     blocks = 0;
1557
1558   files[files_index].name = xstrdup (name);
1559   files_index++;
1560
1561   return blocks;
1562 }
1563
1564 #ifdef S_ISLNK
1565
1566 /* Put the name of the file that `filename' is a symbolic link to
1567    into the `linkname' field of `f'. */
1568
1569 static void
1570 get_link_name (filename, f)
1571      char *filename;
1572      struct fileinfo *f;
1573 {
1574   char *linkbuf;
1575   register int linksize;
1576
1577   linkbuf = (char *) alloca (PATH_MAX + 2);
1578   /* Some automounters give incorrect st_size for mount points.
1579      I can't think of a good workaround for it, though.  */
1580   linksize = readlink (filename, linkbuf, PATH_MAX + 1);
1581   if (linksize < 0)
1582     {
1583       error (0, errno, "%s", filename);
1584       exit_status = 1;
1585     }
1586   else
1587     {
1588       linkbuf[linksize] = '\0';
1589       f->linkname = xstrdup (linkbuf);
1590     }
1591 }
1592
1593 /* If `linkname' is a relative path and `path' contains one or more
1594    leading directories, return `linkname' with those directories
1595    prepended; otherwise, return a copy of `linkname'.
1596    If `linkname' is zero, return zero. */
1597
1598 static char *
1599 make_link_path (path, linkname)
1600      char *path;
1601      char *linkname;
1602 {
1603   char *linkbuf;
1604   int bufsiz;
1605
1606   if (linkname == 0)
1607     return 0;
1608
1609   if (*linkname == '/')
1610     return xstrdup (linkname);
1611
1612   /* The link is to a relative path.  Prepend any leading path
1613      in `path' to the link name. */
1614   linkbuf = strrchr (path, '/');
1615   if (linkbuf == 0)
1616     return xstrdup (linkname);
1617
1618   bufsiz = linkbuf - path + 1;
1619   linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);
1620   strncpy (linkbuf, path, bufsiz);
1621   strcpy (linkbuf + bufsiz, linkname);
1622   return linkbuf;
1623 }
1624 #endif
1625
1626 /* Remove any entries from `files' that are for directories,
1627    and queue them to be listed as directories instead.
1628    `dirname' is the prefix to prepend to each dirname
1629    to make it correct relative to ls's working dir.
1630    `recursive' is nonzero if we should not treat `.' and `..' as dirs.
1631    This is desirable when processing directories recursively.  */
1632
1633 static void
1634 extract_dirs_from_files (dirname, recursive)
1635      char *dirname;
1636      int recursive;
1637 {
1638   register int i, j;
1639   register char *path;
1640   int dirlen;
1641
1642   dirlen = strlen (dirname) + 2;
1643   /* Queue the directories last one first, because queueing reverses the
1644      order.  */
1645   for (i = files_index - 1; i >= 0; i--)
1646     if ((files[i].filetype == directory || files[i].filetype == arg_directory)
1647         && (!recursive || is_not_dot_or_dotdot (files[i].name)))
1648       {
1649         if (files[i].name[0] == '/' || dirname[0] == 0)
1650           {
1651             queue_directory (files[i].name, files[i].linkname);
1652           }
1653         else
1654           {
1655             path = (char *) xmalloc (strlen (files[i].name) + dirlen);
1656             attach (path, dirname, files[i].name);
1657             queue_directory (path, files[i].linkname);
1658             free (path);
1659           }
1660         if (files[i].filetype == arg_directory)
1661           free (files[i].name);
1662       }
1663
1664   /* Now delete the directories from the table, compacting all the remaining
1665      entries.  */
1666
1667   for (i = 0, j = 0; i < files_index; i++)
1668     if (files[i].filetype != arg_directory)
1669       files[j++] = files[i];
1670   files_index = j;
1671 }
1672 \f
1673 /* Return non-zero if `name' doesn't end in `.' or `..'
1674    This is so we don't try to recurse on `././././. ...' */
1675
1676 static int
1677 is_not_dot_or_dotdot (name)
1678      char *name;
1679 {
1680   char *t;
1681
1682   t = strrchr (name, '/');
1683   if (t)
1684     name = t + 1;
1685
1686   if (name[0] == '.'
1687       && (name[1] == '\0'
1688           || (name[1] == '.' && name[2] == '\0')))
1689     return 0;
1690
1691   return 1;
1692 }
1693 \f
1694 /* Sort the files now in the table.  */
1695
1696 static void
1697 sort_files ()
1698 {
1699   int (*func) ();
1700
1701   switch (sort_type)
1702     {
1703     case sort_none:
1704       return;
1705     case sort_time:
1706       switch (time_type)
1707         {
1708         case time_ctime:
1709           func = sort_reverse ? rev_cmp_ctime : compare_ctime;
1710           break;
1711         case time_mtime:
1712           func = sort_reverse ? rev_cmp_mtime : compare_mtime;
1713           break;
1714         case time_atime:
1715           func = sort_reverse ? rev_cmp_atime : compare_atime;
1716           break;
1717         default:
1718           abort ();
1719         }
1720       break;
1721     case sort_name:
1722       func = sort_reverse ? rev_cmp_name : compare_name;
1723       break;
1724     case sort_extension:
1725       func = sort_reverse ? rev_cmp_extension : compare_extension;
1726       break;
1727     case sort_size:
1728       func = sort_reverse ? rev_cmp_size : compare_size;
1729       break;
1730     default:
1731       abort ();
1732     }
1733
1734   qsort (files, files_index, sizeof (struct fileinfo), func);
1735 }
1736
1737 /* Comparison routines for sorting the files. */
1738
1739 static int
1740 compare_ctime (file1, file2)
1741      struct fileinfo *file1, *file2;
1742 {
1743   return longdiff (file2->stat.st_ctime, file1->stat.st_ctime);
1744 }
1745
1746 static int
1747 rev_cmp_ctime (file2, file1)
1748      struct fileinfo *file1, *file2;
1749 {
1750   return longdiff (file2->stat.st_ctime, file1->stat.st_ctime);
1751 }
1752
1753 static int
1754 compare_mtime (file1, file2)
1755      struct fileinfo *file1, *file2;
1756 {
1757   return longdiff (file2->stat.st_mtime, file1->stat.st_mtime);
1758 }
1759
1760 static int
1761 rev_cmp_mtime (file2, file1)
1762      struct fileinfo *file1, *file2;
1763 {
1764   return longdiff (file2->stat.st_mtime, file1->stat.st_mtime);
1765 }
1766
1767 static int
1768 compare_atime (file1, file2)
1769      struct fileinfo *file1, *file2;
1770 {
1771   return longdiff (file2->stat.st_atime, file1->stat.st_atime);
1772 }
1773
1774 static int
1775 rev_cmp_atime (file2, file1)
1776      struct fileinfo *file1, *file2;
1777 {
1778   return longdiff (file2->stat.st_atime, file1->stat.st_atime);
1779 }
1780
1781 static int
1782 compare_size (file1, file2)
1783      struct fileinfo *file1, *file2;
1784 {
1785   return longdiff (file2->stat.st_size, file1->stat.st_size);
1786 }
1787
1788 static int
1789 rev_cmp_size (file2, file1)
1790      struct fileinfo *file1, *file2;
1791 {
1792   return longdiff (file2->stat.st_size, file1->stat.st_size);
1793 }
1794
1795 static int
1796 compare_name (file1, file2)
1797      struct fileinfo *file1, *file2;
1798 {
1799   return strcmp (file1->name, file2->name);
1800 }
1801
1802 static int
1803 rev_cmp_name (file2, file1)
1804      struct fileinfo *file1, *file2;
1805 {
1806   return strcmp (file1->name, file2->name);
1807 }
1808
1809 /* Compare file extensions.  Files with no extension are `smallest'.
1810    If extensions are the same, compare by filenames instead. */
1811
1812 static int
1813 compare_extension (file1, file2)
1814      struct fileinfo *file1, *file2;
1815 {
1816   register char *base1, *base2;
1817   register int cmp;
1818
1819   base1 = strrchr (file1->name, '.');
1820   base2 = strrchr (file2->name, '.');
1821   if (base1 == 0 && base2 == 0)
1822     return strcmp (file1->name, file2->name);
1823   if (base1 == 0)
1824     return -1;
1825   if (base2 == 0)
1826     return 1;
1827   cmp = strcmp (base1, base2);
1828   if (cmp == 0)
1829     return strcmp (file1->name, file2->name);
1830   return cmp;
1831 }
1832
1833 static int
1834 rev_cmp_extension (file2, file1)
1835      struct fileinfo *file1, *file2;
1836 {
1837   register char *base1, *base2;
1838   register int cmp;
1839
1840   base1 = strrchr (file1->name, '.');
1841   base2 = strrchr (file2->name, '.');
1842   if (base1 == 0 && base2 == 0)
1843     return strcmp (file1->name, file2->name);
1844   if (base1 == 0)
1845     return -1;
1846   if (base2 == 0)
1847     return 1;
1848   cmp = strcmp (base1, base2);
1849   if (cmp == 0)
1850     return strcmp (file1->name, file2->name);
1851   return cmp;
1852 }
1853 \f
1854 /* List all the files now in the table.  */
1855
1856 static void
1857 print_current_files ()
1858 {
1859   register int i;
1860
1861   switch (format)
1862     {
1863     case one_per_line:
1864       for (i = 0; i < files_index; i++)
1865         {
1866           print_file_name_and_frills (files + i);
1867           putchar ('\n');
1868         }
1869       break;
1870
1871     case many_per_line:
1872       print_many_per_line ();
1873       break;
1874
1875     case horizontal:
1876       print_horizontal ();
1877       break;
1878
1879     case with_commas:
1880       print_with_commas ();
1881       break;
1882
1883     case long_format:
1884       for (i = 0; i < files_index; i++)
1885         {
1886           print_long_format (files + i);
1887           PUTCHAR ('\n');
1888         }
1889       break;
1890     }
1891 }
1892
1893 static void
1894 print_long_format (f)
1895      struct fileinfo *f;
1896 {
1897   char modebuf[20];
1898   char timebuf[40];
1899
1900   /* 7 fields that may (worst case be 64-bit integral values) require 20 bytes,
1901      10 character mode field,
1902      24 characters for the time,
1903      9 spaces following each of these fields,
1904      and 1 trailing NUL byte.  */
1905   char bigbuf[7 * 20 + 10 + 24 + 9 + 1];
1906   char *p;
1907   time_t when;
1908
1909   mode_string (f->stat.st_mode, modebuf);
1910   modebuf[10] = '\0';
1911
1912   switch (time_type)
1913     {
1914     case time_ctime:
1915       when = f->stat.st_ctime;
1916       break;
1917     case time_mtime:
1918       when = f->stat.st_mtime;
1919       break;
1920     case time_atime:
1921       when = f->stat.st_atime;
1922       break;
1923     }
1924
1925   strcpy (timebuf, ctime (&when));
1926
1927   if (full_time)
1928     timebuf[24] = '\0';
1929   else
1930     {
1931       if (current_time > when + 6L * 30L * 24L * 60L * 60L      /* Old. */
1932           || current_time < when - 60L * 60L)   /* In the future. */
1933         {
1934           /* The file is fairly old or in the future.
1935              POSIX says the cutoff is 6 months old;
1936              approximate this by 6*30 days.
1937              Allow a 1 hour slop factor for what is considered "the future",
1938              to allow for NFS server/client clock disagreement.
1939              Show the year instead of the time of day.  */
1940           strcpy (timebuf + 11, timebuf + 19);
1941         }
1942       timebuf[16] = 0;
1943     }
1944
1945   p = bigbuf;
1946
1947   if (print_inode)
1948     {
1949       sprintf (p, "%*lu ", INODE_DIGITS, (unsigned long) f->stat.st_ino);
1950       p += strlen (p);
1951     }
1952
1953   if (print_block_size)
1954     {
1955       sprintf (p, "%*u ", block_size_size,
1956                (unsigned) convert_blocks (ST_NBLOCKS (f->stat),
1957                                           kilobyte_blocks));
1958       p += strlen (p);
1959     }
1960
1961   /* The space between the mode and the number of links is the POSIX
1962      "optional alternate access method flag". */
1963   sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink);
1964   p += strlen (p);
1965
1966   if (numeric_users)
1967     sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
1968   else
1969     sprintf (p, "%-8.8s ", getuser (f->stat.st_uid));
1970   p += strlen (p);
1971
1972   if (!inhibit_group)
1973     {
1974       if (numeric_users)
1975         sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid);
1976       else
1977         sprintf (p, "%-8.8s ", getgroup (f->stat.st_gid));
1978       p += strlen (p);
1979     }
1980
1981   if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
1982     sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
1983              (unsigned) minor (f->stat.st_rdev));
1984   else
1985     sprintf (p, "%8lu ", (unsigned long) f->stat.st_size);
1986   p += strlen (p);
1987
1988   sprintf (p, "%s ", full_time ? timebuf : timebuf + 4);
1989   p += strlen (p);
1990
1991   DIRED_INDENT ();
1992   FPUTS (bigbuf, stdout, p - bigbuf);
1993   PUSH_CURRENT_DIRED_POS (&dired_obstack);
1994   if (print_with_color)
1995     print_color_indicator (f->stat.st_mode);
1996   print_name_with_quoting (f->name);
1997   if (print_with_color)
1998     put_indicator (C_END);
1999   PUSH_CURRENT_DIRED_POS (&dired_obstack);
2000
2001   if (f->filetype == symbolic_link)
2002     {
2003       if (f->linkname)
2004         {
2005           FPUTS_LITERAL (" -> ", stdout);
2006           if (print_with_color)
2007             print_color_indicator (f->linkmode);
2008           print_name_with_quoting (f->linkname);
2009           if (print_with_color)
2010             put_indicator (C_END);
2011           if (indicator_style != none)
2012             print_type_indicator (f->linkmode);
2013         }
2014     }
2015   else if (indicator_style != none)
2016     print_type_indicator (f->stat.st_mode);
2017 }
2018 \f
2019 /* Set QUOTED_LENGTH to strlen(P) and return NULL if P == quoted(P).
2020    Otherwise, return xmalloc'd storage containing the quoted version
2021    of P and set QUOTED_LENGTH to the length of the quoted P.  */
2022
2023 static char *
2024 quote_filename (p, quoted_length)
2025      register const char *p;
2026      size_t *quoted_length;
2027 {
2028   register unsigned char c;
2029   const char *p0 = p;
2030   char *quoted, *q;
2031   int found_quotable;
2032
2033   if (!quote_as_string && !quote_funny_chars && !qmark_funny_chars)
2034     {
2035       *quoted_length = strlen (p);
2036       return NULL;
2037     }
2038
2039   found_quotable = 0;
2040   for (c = *p; c; c = *++p)
2041     {
2042       if (quote_funny_chars)
2043         {
2044           switch (c)
2045             {
2046             case '\\':
2047             case '\n':
2048             case '\b':
2049             case '\r':
2050             case '\t':
2051             case '\f':
2052             case ' ':
2053             case '"':
2054               found_quotable = 1;
2055               break;
2056
2057             default:
2058               /* FIXME: why not just use the ISPRINT macro here?  */
2059               if (!((c > 040 && c < 0177)
2060                     || (print_iso8859 && c >= 0200 && c <= 0377)))
2061                 found_quotable = 1;
2062               break;
2063             }
2064         }
2065       else
2066         {
2067           if (!((c >= 040 && c < 0177)
2068                 || (print_iso8859 && c >= 0xA1 && c <= 0xFF))
2069               && qmark_funny_chars)
2070             found_quotable = 1;
2071         }
2072       if (found_quotable)
2073         break;
2074     }
2075
2076   if (!found_quotable && !quote_as_string)
2077     {
2078       *quoted_length = p - p0;
2079       return NULL;
2080     }
2081
2082   p = p0;
2083   quoted = xmalloc (4 * strlen (p) + 1);
2084   q = quoted;
2085
2086 #define SAVECHAR(c) *q++ = (c)
2087 #define SAVE_2_CHARS(c12) \
2088     do { *q++ = ((c12)[0]); \
2089          *q++ = ((c12)[1]); } while (0)
2090
2091   if (quote_as_string)
2092     SAVECHAR ('"');
2093
2094   while ((c = *p++))
2095     {
2096       if (quote_funny_chars)
2097         {
2098           switch (c)
2099             {
2100             case '\\':
2101               SAVE_2_CHARS ("\\\\");
2102               break;
2103
2104             case '\n':
2105               SAVE_2_CHARS ("\\n");
2106               break;
2107
2108             case '\b':
2109               SAVE_2_CHARS ("\\b");
2110               break;
2111
2112             case '\r':
2113               SAVE_2_CHARS ("\\r");
2114               break;
2115
2116             case '\t':
2117               SAVE_2_CHARS ("\\t");
2118               break;
2119
2120             case '\f':
2121               SAVE_2_CHARS ("\\f");
2122               break;
2123
2124             case ' ':
2125               SAVE_2_CHARS ("\\ ");
2126               break;
2127
2128             case '"':
2129               SAVE_2_CHARS ("\\\"");
2130               break;
2131
2132             default:
2133               if ((c > 040 && c < 0177)
2134                   || (print_iso8859 && c >= 0200 && c <= 0377))
2135                 SAVECHAR (c);
2136               else
2137                 {
2138                   char buf[5];
2139                   sprintf (buf, "\\%03o", (unsigned int) c);
2140                   q = stpcpy (q, buf);
2141                 }
2142             }
2143         }
2144       else
2145         {
2146           if ((c >= 040 && c < 0177)
2147               || (print_iso8859 && c >= 0200 && c <= 0377))
2148             SAVECHAR (c);
2149           else if (!qmark_funny_chars)
2150             SAVECHAR (c);
2151           else
2152             SAVECHAR ('?');
2153         }
2154     }
2155
2156   if (quote_as_string)
2157     SAVECHAR ('"');
2158
2159   *quoted_length = q - quoted;
2160
2161   SAVECHAR ('\0');
2162
2163   return quoted;
2164 }
2165
2166 static void
2167 print_name_with_quoting (p)
2168      register char *p;
2169 {
2170   char *quoted;
2171   size_t quoted_length;
2172
2173   quoted = quote_filename (p, &quoted_length);
2174   FPUTS (quoted != NULL ? quoted : p, stdout, quoted_length);
2175   if (quoted)
2176     free (quoted);
2177 }
2178 \f
2179 /* Print the file name of `f' with appropriate quoting.
2180    Also print file size, inode number, and filetype indicator character,
2181    as requested by switches.  */
2182
2183 static void
2184 print_file_name_and_frills (f)
2185      struct fileinfo *f;
2186 {
2187   if (print_inode)
2188     printf ("%*lu ", INODE_DIGITS, (unsigned long) f->stat.st_ino);
2189
2190   if (print_block_size)
2191     printf ("%*u ", block_size_size,
2192             (unsigned) convert_blocks (ST_NBLOCKS (f->stat),
2193                                        kilobyte_blocks));
2194
2195   if (print_with_color)
2196     print_color_indicator (f->stat.st_mode);
2197   print_name_with_quoting (f->name);
2198   if (print_with_color)
2199     put_indicator (C_END);
2200
2201   if (indicator_style != none)
2202     print_type_indicator (f->stat.st_mode);
2203 }
2204
2205 static void
2206 print_type_indicator (mode)
2207      unsigned int mode;
2208 {
2209   if (S_ISDIR (mode))
2210     PUTCHAR ('/');
2211
2212 #ifdef S_ISLNK
2213   if (S_ISLNK (mode))
2214     PUTCHAR ('@');
2215 #endif
2216
2217 #ifdef S_ISFIFO
2218   if (S_ISFIFO (mode))
2219     PUTCHAR ('|');
2220 #endif
2221
2222 #ifdef S_ISSOCK
2223   if (S_ISSOCK (mode))
2224     PUTCHAR ('=');
2225 #endif
2226
2227   if (S_ISREG (mode) && indicator_style == all
2228       && (mode & (S_IEXEC | S_IXGRP | S_IXOTH)))
2229     PUTCHAR ('*');
2230 }
2231
2232 static void
2233 print_color_indicator (mode)
2234      unsigned int mode;
2235 {
2236   int type = C_FILE;
2237
2238   if (S_ISDIR (mode))
2239     type = C_DIR;
2240
2241 #ifdef S_ISLNK
2242   else if (S_ISLNK (mode))
2243     type = C_LINK;
2244 #endif
2245
2246 #ifdef S_ISFIFO
2247   else if (S_ISFIFO (mode))
2248     type = C_FIFO;
2249 #endif
2250
2251 #ifdef S_ISSOCK
2252   else if (S_ISSOCK (mode))
2253     type = C_SOCK;
2254 #endif
2255
2256 #ifdef S_ISBLK
2257   else if (S_ISBLK (mode))
2258     type = C_BLK;
2259 #endif
2260
2261 #ifdef S_ISCHR
2262   else if (S_ISCHR (mode))
2263     type = C_CHR;
2264 #endif
2265
2266   if (type == C_FILE && (mode & (S_IEXEC | S_IEXEC >> 3 | S_IEXEC >> 6)))
2267     type = C_EXEC;
2268
2269   put_indicator (C_LEFT);
2270   put_indicator (type);
2271   put_indicator (C_RIGHT);
2272 }
2273
2274 /* Output a color indicator (which may contain nulls) */
2275 static void
2276 put_indicator (n)
2277      int n;
2278 {
2279   register int i;
2280   register char *p;
2281
2282   p = color_indicator[n].string;
2283
2284   for (i = color_indicator[n].len; i; i--)
2285     {
2286       putchar (*(p++));
2287     }
2288 }
2289
2290 static int
2291 length_of_file_name_and_frills (f)
2292      struct fileinfo *f;
2293 {
2294   register char *p = f->name;
2295   register unsigned char c;
2296   register int len = 0;
2297
2298   if (print_inode)
2299     len += INODE_DIGITS + 1;
2300
2301   if (print_block_size)
2302     len += 1 + block_size_size;
2303
2304   if (quote_as_string)
2305     len += 2;
2306
2307   while ((c = *p++))
2308     {
2309       if (quote_funny_chars)
2310         {
2311           switch (c)
2312             {
2313             case '\\':
2314             case '\n':
2315             case '\b':
2316             case '\r':
2317             case '\t':
2318             case '\f':
2319             case ' ':
2320               len += 2;
2321               break;
2322
2323             case '"':
2324               if (quote_as_string)
2325                 len += 2;
2326               else
2327                 len += 1;
2328               break;
2329
2330             default:
2331               if ((c >= 040 && c < 0177)
2332                   || (print_iso8859 && c >= 0200 && c <= 0377))
2333                 len += 1;
2334               else
2335                 len += 4;
2336             }
2337         }
2338       else
2339         len += 1;
2340     }
2341
2342   if (indicator_style != none)
2343     {
2344       unsigned filetype = f->stat.st_mode;
2345
2346       if (S_ISREG (filetype))
2347         {
2348           if (indicator_style == all
2349               && (f->stat.st_mode & (S_IEXEC | S_IEXEC >> 3 | S_IEXEC >> 6)))
2350             len += 1;
2351         }
2352       else if (S_ISDIR (filetype)
2353 #ifdef S_ISLNK
2354                || S_ISLNK (filetype)
2355 #endif
2356 #ifdef S_ISFIFO
2357                || S_ISFIFO (filetype)
2358 #endif
2359 #ifdef S_ISSOCK
2360                || S_ISSOCK (filetype)
2361 #endif
2362         )
2363         len += 1;
2364     }
2365
2366   return len;
2367 }
2368 \f
2369 static void
2370 print_many_per_line ()
2371 {
2372   int filesno;                  /* Index into files. */
2373   int row;                      /* Current row. */
2374   int max_name_length;          /* Length of longest file name + frills. */
2375   int name_length;              /* Length of each file name + frills. */
2376   int pos;                      /* Current character column. */
2377   int cols;                     /* Number of files across. */
2378   int rows;                     /* Maximum number of files down. */
2379
2380   /* Compute the maximum file name length.  */
2381   max_name_length = 0;
2382   for (filesno = 0; filesno < files_index; filesno++)
2383     {
2384       name_length = length_of_file_name_and_frills (files + filesno);
2385       if (name_length > max_name_length)
2386         max_name_length = name_length;
2387     }
2388
2389   /* Allow at least two spaces between names.  */
2390   max_name_length += 2;
2391
2392   /* Calculate the maximum number of columns that will fit. */
2393   cols = line_length / max_name_length;
2394   if (cols == 0)
2395     cols = 1;
2396   /* Calculate the number of rows that will be in each column except possibly
2397      for a short column on the right. */
2398   rows = files_index / cols + (files_index % cols != 0);
2399   /* Recalculate columns based on rows. */
2400   cols = files_index / rows + (files_index % rows != 0);
2401
2402   for (row = 0; row < rows; row++)
2403     {
2404       filesno = row;
2405       pos = 0;
2406       /* Print the next row.  */
2407       while (1)
2408         {
2409           print_file_name_and_frills (files + filesno);
2410           name_length = length_of_file_name_and_frills (files + filesno);
2411
2412           filesno += rows;
2413           if (filesno >= files_index)
2414             break;
2415
2416           indent (pos + name_length, pos + max_name_length);
2417           pos += max_name_length;
2418         }
2419       putchar ('\n');
2420     }
2421 }
2422 \f
2423 static void
2424 print_horizontal ()
2425 {
2426   int filesno;
2427   int max_name_length;
2428   int name_length;
2429   int cols;
2430   int pos;
2431
2432   /* Compute the maximum file name length.  */
2433   max_name_length = 0;
2434   for (filesno = 0; filesno < files_index; filesno++)
2435     {
2436       name_length = length_of_file_name_and_frills (files + filesno);
2437       if (name_length > max_name_length)
2438         max_name_length = name_length;
2439     }
2440
2441   /* Allow two spaces between names.  */
2442   max_name_length += 2;
2443
2444   cols = line_length / max_name_length;
2445   if (cols == 0)
2446     cols = 1;
2447
2448   pos = 0;
2449   name_length = 0;
2450
2451   for (filesno = 0; filesno < files_index; filesno++)
2452     {
2453       if (filesno != 0)
2454         {
2455           if (filesno % cols == 0)
2456             {
2457               putchar ('\n');
2458               pos = 0;
2459             }
2460           else
2461             {
2462               indent (pos + name_length, pos + max_name_length);
2463               pos += max_name_length;
2464             }
2465         }
2466
2467       print_file_name_and_frills (files + filesno);
2468
2469       name_length = length_of_file_name_and_frills (files + filesno);
2470     }
2471   putchar ('\n');
2472 }
2473 \f
2474 static void
2475 print_with_commas ()
2476 {
2477   int filesno;
2478   int pos, old_pos;
2479
2480   pos = 0;
2481
2482   for (filesno = 0; filesno < files_index; filesno++)
2483     {
2484       old_pos = pos;
2485
2486       pos += length_of_file_name_and_frills (files + filesno);
2487       if (filesno + 1 < files_index)
2488         pos += 2;               /* For the comma and space */
2489
2490       if (old_pos != 0 && pos >= line_length)
2491         {
2492           putchar ('\n');
2493           pos -= old_pos;
2494         }
2495
2496       print_file_name_and_frills (files + filesno);
2497       if (filesno + 1 < files_index)
2498         {
2499           putchar (',');
2500           putchar (' ');
2501         }
2502     }
2503   putchar ('\n');
2504 }
2505 \f
2506 /* Assuming cursor is at position FROM, indent up to position TO.
2507    Use a TAB character instead of two or more spaces whenever possible.  */
2508
2509 static void
2510 indent (from, to)
2511      int from, to;
2512 {
2513   while (from < to)
2514     {
2515       if (to / tabsize > (from + 1) / tabsize)
2516         {
2517           putchar ('\t');
2518           from += tabsize - from % tabsize;
2519         }
2520       else
2521         {
2522           putchar (' ');
2523           from++;
2524         }
2525     }
2526 }
2527
2528 /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */
2529
2530 static void
2531 attach (dest, dirname, name)
2532      char *dest, *dirname, *name;
2533 {
2534   char *dirnamep = dirname;
2535
2536   /* Copy dirname if it is not ".". */
2537   if (dirname[0] != '.' || dirname[1] != 0)
2538     {
2539       while (*dirnamep)
2540         *dest++ = *dirnamep++;
2541       /* Add '/' if `dirname' doesn't already end with it. */
2542       if (dirnamep > dirname && dirnamep[-1] != '/')
2543         *dest++ = '/';
2544     }
2545   while (*name)
2546     *dest++ = *name++;
2547   *dest = 0;
2548 }
2549
2550 static void
2551 usage (status)
2552      int status;
2553 {
2554   if (status != 0)
2555     fprintf (stderr, "Try `%s --help' for more information.\n",
2556              program_name);
2557   else
2558     {
2559       printf ("Usage: %s [OPTION]... [PATH]...\n", program_name);
2560       printf ("\
2561 \n\
2562   -A, --almost-all           do not list implied . and ..\n\
2563   -a, --all                  do not hide entries starting with .\n\
2564   -B, --ignore-backups       do not list implied entries ending with ~\n\
2565   -b, --escape               print octal escapes for nongraphic characters\n\
2566   -C                         list entries by columns\n\
2567   -c                         sort by change time; with -l: show ctime\n\
2568   -D, --dired                generate output well suited to Emacs' dired mode\n\
2569   -d, --directory            list directory entries instead of contents\n\
2570   -F, --classify             append a character for typing each entry\n\
2571   -f                         do not sort, enable -aU, disable -lst\n\
2572       --format=WORD          across -x, commas -m, horizontal -x, long -l,\n\
2573                                single-column -1, verbose -l, vertical -C\n\
2574       --full-time            list both full date and full time\n");
2575
2576       printf ("\
2577   -G, --no-group             inhibit display of group information\n\
2578   -g                         (ignored)\n\
2579   -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN\n\
2580   -i, --inode                print index number of each file\n\
2581   -k, --kilobytes            use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\
2582   -L, --dereference          list entries pointed to by symbolic links\n\
2583   -l                         use a long listing format\n\
2584   -m                         fill width with a comma separated list of entries\n\
2585   -N, --literal              do not quote entry names\n\
2586   -n, --numeric-uid-gid      list numeric UIDs and GIDs instead of names\n\
2587   -o, --color, --colour      colorize entries according to type\n\
2588       --colo(u)r=WORD        yes -o, no, tty (if output is a terminal)\n\
2589   -p                         append a character for typing each entry\n\
2590   -Q, --quote-name           enclose entry names in double quotes\n\
2591   -q, --hide-control-chars   print ? instead of non graphic characters\n\
2592   -R, --recursive            list subdirectories recursively\n\
2593   -r, --reverse              reverse order while sorting\n\
2594   -S                         sort by file size\n");
2595
2596       printf ("\
2597   -s, --size                 print block size of each file\n\
2598       --sort=WORD            ctime -c, extension -X, none -U, size -S,\n\
2599                                status -c, time -t\n\
2600       --time=WORD            atime -u, access -u, use -u\n\
2601   -T, --tabsize=COLS         assume tab stops at each COLS instead of 8\n\
2602   -t                         sort by modification time; with -l: show mtime\n\
2603   -U                         do not sort; list entries in directory order\n\
2604   -u                         sort by last access time; with -l: show atime\n\
2605   -w, --width=COLS           assume screen width instead of current value\n\
2606   -x                         list entries by lines instead of by columns\n\
2607   -X                         sort alphabetically by entry extension\n\
2608   -1                         list one file per line\n\
2609   -7, --7bit                 allow only 7-bit ASCII characters to be printed\n\
2610   -8, --8bit                 allow 8-bit ISO 8859 characters to be printed\n\
2611       --help                 display this help and exit\n\
2612       --version              output version information and exit\n\
2613 \n\
2614 Sort entries alphabetically if none of -cftuSUX nor --sort.\n");
2615     }
2616   exit (status);
2617 }