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