.
[coreutils.git] / src / ls.c
blobcd0447002a2f023fa5745465e101ec451ce9b759
1 /* `dir', `vdir' and `ls' directory listing programs for GNU.
2 Copyright (C) 85, 88, 90, 91, 95, 96, 97, 1998 Free Software Foundation, Inc.
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.
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.
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. */
18 /* If ls_mode is LS_MULTI_COL,
19 the multi-column format is the default regardless
20 of the type of output device.
21 This is for the `dir' program.
23 If ls_mode is LS_LONG_FORMAT,
24 the long format is the default regardless of the
25 type of output device.
26 This is for the `vdir' program.
28 If ls_mode is LS_LS,
29 the output format depends on whether the output
30 device is a terminal.
31 This is for the `ls' program. */
33 /* Written by Richard Stallman and David MacKenzie. */
35 /* Color 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>. */
39 #ifdef _AIX
40 #pragma alloca
41 #endif
43 #include <config.h>
44 #include <sys/types.h>
46 #if HAVE_INTTYPES_H
47 # include <inttypes.h>
48 #endif
50 #ifdef HAVE_TERMIOS_H
51 # include <termios.h>
52 #endif
54 #ifdef GWINSZ_IN_SYS_IOCTL
55 # include <sys/ioctl.h>
56 #endif
58 #include <stdio.h>
59 #include <grp.h>
60 #include <pwd.h>
61 #include <getopt.h>
63 #include "system.h"
64 #include <fnmatch.h>
66 #include "obstack.h"
67 #include "ls.h"
68 #include "closeout.h"
69 #include "error.h"
70 #include "human.h"
71 #include "argmatch.h"
72 #include "xstrtol.h"
73 #include "strverscmp.h"
75 #define obstack_chunk_alloc malloc
76 #define obstack_chunk_free free
78 /* Return an int indicating the result of comparing two integers.
79 Subtracting doesn't always work, due to overflow. */
80 #define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))
82 /* The field width for inode numbers. On some hosts inode numbers are
83 64 bits, so columns won't line up exactly when a huge inode number
84 is encountered, but in practice 7 digits is usually enough. */
85 #ifndef INODE_DIGITS
86 # define INODE_DIGITS 7
87 #endif
89 enum filetype
91 symbolic_link,
92 directory,
93 arg_directory, /* Directory given as command line arg. */
94 normal /* All others. */
97 struct fileinfo
99 /* The file name. */
100 char *name;
102 struct stat stat;
104 /* For symbolic link, name of the file linked to, otherwise zero. */
105 char *linkname;
107 /* For symbolic link and long listing, st_mode of file linked to, otherwise
108 zero. */
109 unsigned int linkmode;
111 /* For symbolic link and color printing, 1 if linked-to file
112 exists, otherwise 0. */
113 int linkok;
115 enum filetype filetype;
118 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
120 /* Null is a valid character in a color indicator (think about Epson
121 printers, for example) so we have to use a length/buffer string
122 type. */
124 struct bin_str
126 int len; /* Number of bytes */
127 char *string; /* Pointer to the same */
130 #ifndef STDC_HEADERS
131 time_t time ();
132 #endif
134 void mode_string ();
136 char *getgroup ();
137 char *getuser ();
138 void strip_trailing_slashes ();
139 char *xstrdup ();
140 void invalid_arg ();
142 static size_t quote_filename PARAMS ((FILE *out, const char *filename));
143 static char *make_link_path PARAMS ((const char *path, const char *linkname));
144 static int compare_atime PARAMS ((const struct fileinfo *file1,
145 const struct fileinfo *file2));
146 static int rev_cmp_atime PARAMS ((const struct fileinfo *file2,
147 const struct fileinfo *file1));
148 static int compare_ctime PARAMS ((const struct fileinfo *file1,
149 const struct fileinfo *file2));
150 static int rev_cmp_ctime PARAMS ((const struct fileinfo *file2,
151 const struct fileinfo *file1));
152 static int compare_mtime PARAMS ((const struct fileinfo *file1,
153 const struct fileinfo *file2));
154 static int rev_cmp_mtime PARAMS ((const struct fileinfo *file2,
155 const struct fileinfo *file1));
156 static int compare_size PARAMS ((const struct fileinfo *file1,
157 const struct fileinfo *file2));
158 static int rev_cmp_size PARAMS ((const struct fileinfo *file2,
159 const struct fileinfo *file1));
160 static int compare_name PARAMS ((const struct fileinfo *file1,
161 const struct fileinfo *file2));
162 static int rev_cmp_name PARAMS ((const struct fileinfo *file2,
163 const struct fileinfo *file1));
164 static int compare_extension PARAMS ((const struct fileinfo *file1,
165 const struct fileinfo *file2));
166 static int rev_cmp_extension PARAMS ((const struct fileinfo *file2,
167 const struct fileinfo *file1));
168 static int compare_version PARAMS ((const struct fileinfo *file1,
169 const struct fileinfo *file2));
170 static int rev_cmp_version PARAMS ((const struct fileinfo *file2,
171 const struct fileinfo *file1));
172 static int decode_switches PARAMS ((int argc, char **argv));
173 static int file_interesting PARAMS ((const struct dirent *next));
174 static uintmax_t gobble_file PARAMS ((const char *name, int explicit_arg,
175 const char *dirname));
176 static int is_not_dot_or_dotdot PARAMS ((const char *name));
177 static void print_color_indicator PARAMS ((const char *name, unsigned int mode,
178 int linkok));
179 static void put_indicator PARAMS ((const struct bin_str *ind));
180 static int length_of_file_name_and_frills PARAMS ((const struct fileinfo *f));
181 static void add_ignore_pattern PARAMS ((const char *pattern));
182 static void attach PARAMS ((char *dest, const char *dirname, const char *name));
183 static void clear_files PARAMS ((void));
184 static void extract_dirs_from_files PARAMS ((const char *dirname,
185 int recursive));
186 static void get_link_name PARAMS ((const char *filename, struct fileinfo *f));
187 static void indent PARAMS ((int from, int to));
188 static void init_col_info PARAMS ((void));
189 static void print_current_files PARAMS ((void));
190 static void print_dir PARAMS ((const char *name, const char *realname));
191 static void print_file_name_and_frills PARAMS ((const struct fileinfo *f));
192 static void print_horizontal PARAMS ((void));
193 static void print_long_format PARAMS ((const struct fileinfo *f));
194 static void print_many_per_line PARAMS ((void));
195 static void print_name_with_quoting PARAMS ((const char *p, unsigned int mode,
196 int linkok,
197 struct obstack *stack));
198 static void prep_non_filename_text PARAMS ((void));
199 static void print_type_indicator PARAMS ((unsigned int mode));
200 static void print_with_commas PARAMS ((void));
201 static void queue_directory PARAMS ((const char *name, const char *realname));
202 static void sort_files PARAMS ((void));
203 static void parse_ls_color PARAMS ((void));
204 static void usage PARAMS ((int status));
206 /* The name the program was run with, stripped of any leading path. */
207 char *program_name;
209 /* The table of files in the current directory:
211 `files' points to a vector of `struct fileinfo', one per file.
212 `nfiles' is the number of elements space has been allocated for.
213 `files_index' is the number actually in use. */
215 /* Address of block containing the files that are described. */
217 static struct fileinfo *files;
219 /* Length of block that `files' points to, measured in files. */
221 static int nfiles;
223 /* Index of first unused in `files'. */
225 static int files_index;
227 /* Record of one pending directory waiting to be listed. */
229 struct pending
231 char *name;
232 /* If the directory is actually the file pointed to by a symbolic link we
233 were told to list, `realname' will contain the name of the symbolic
234 link, otherwise zero. */
235 char *realname;
236 struct pending *next;
239 static struct pending *pending_dirs;
241 /* Current time (seconds since 1970). When we are printing a file's time,
242 include the year if it is more than 6 months before this time. */
244 static time_t current_time;
246 /* The number of digits to use for block sizes.
247 4, or more if needed for bigger numbers. */
249 static int block_size_size;
251 /* Option flags */
253 /* long_format for lots of info, one per line.
254 one_per_line for just names, one per line.
255 many_per_line for just names, many per line, sorted vertically.
256 horizontal for just names, many per line, sorted horizontally.
257 with_commas for just names, many per line, separated by commas.
259 -l, -1, -C, -x and -m control this parameter. */
261 enum format
263 long_format, /* -l */
264 one_per_line, /* -1 */
265 many_per_line, /* -C */
266 horizontal, /* -x */
267 with_commas /* -m */
270 static enum format format;
272 /* Type of time to print or sort by. Controlled by -c and -u. */
274 enum time_type
276 time_mtime, /* default */
277 time_ctime, /* -c */
278 time_atime /* -u */
281 static enum time_type time_type;
283 /* print the full time, otherwise the standard unix heuristics. */
285 int full_time;
287 /* The file characteristic to sort by. Controlled by -t, -S, -U, -X, -v. */
289 enum sort_type
291 sort_none, /* -U */
292 sort_name, /* default */
293 sort_extension, /* -X */
294 sort_time, /* -t */
295 sort_size, /* -S */
296 sort_version /* -v */
299 static enum sort_type sort_type;
301 /* Direction of sort.
302 0 means highest first if numeric,
303 lowest first if alphabetic;
304 these are the defaults.
305 1 means the opposite order in each case. -r */
307 static int sort_reverse;
309 /* Nonzero means to NOT display group information. -G */
311 int inhibit_group;
313 /* Nonzero means print the user and group id's as numbers rather
314 than as names. -n */
316 static int numeric_ids;
318 /* Nonzero means mention the size in 512 byte blocks of each file. -s */
320 static int print_block_size;
322 /* The units to count blocks in. */
324 static int output_units;
326 /* Precede each line of long output (per file) with a string like `m,n:'
327 where M is the number of characters after the `:' and before the
328 filename and N is the length of the filename. Using this format,
329 Emacs' dired mode starts up twice as fast, and can handle all
330 strange characters in file names. */
331 static int dired;
333 /* `none' means don't mention the type of files.
334 `all' means mention the types of all files.
335 `not_programs' means do so except for executables.
337 Controlled by -F and -p. */
339 enum indicator_style
341 none, /* default */
342 all, /* -F */
343 not_programs /* -p */
346 static enum indicator_style indicator_style;
348 /* Nonzero means use colors to mark types. Also define the different
349 colors as well as the stuff for the LS_COLORS environment variable.
350 The LS_COLORS variable is now in a termcap-like format. */
352 static int print_with_color;
354 enum color_type
356 color_never, /* 0: default or --color=never */
357 color_always, /* 1: --color=always */
358 color_if_tty /* 2: --color=tty */
361 enum indicator_no
363 C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
364 C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC
367 static const char *const indicator_name[]=
369 "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
370 "bd", "cd", "mi", "or", "ex", NULL
373 struct col_ext_type
375 struct bin_str ext; /* The extension we're looking for */
376 struct bin_str seq; /* The sequence to output when we do */
377 struct col_ext_type *next; /* Next in list */
380 static struct bin_str color_indicator[] =
382 { LEN_STR_PAIR ("\033[") }, /* lc: Left of color sequence */
383 { LEN_STR_PAIR ("m") }, /* rc: Right of color sequence */
384 { 0, NULL }, /* ec: End color (replaces lc+no+rc) */
385 { LEN_STR_PAIR ("0") }, /* no: Normal */
386 { LEN_STR_PAIR ("0") }, /* fi: File: default */
387 { LEN_STR_PAIR ("01;34") }, /* di: Directory: bright blue */
388 { LEN_STR_PAIR ("01;36") }, /* ln: Symlink: bright cyan */
389 { LEN_STR_PAIR ("33") }, /* pi: Pipe: yellow/brown */
390 { LEN_STR_PAIR ("01;35") }, /* so: Socket: bright magenta */
391 { LEN_STR_PAIR ("01;33") }, /* bd: Block device: bright yellow */
392 { LEN_STR_PAIR ("01;33") }, /* cd: Char device: bright yellow */
393 { 0, NULL }, /* mi: Missing file: undefined */
394 { 0, NULL }, /* or: Orphanned symlink: undefined */
395 { LEN_STR_PAIR ("01;32") } /* ex: Executable: bright green */
398 /* FIXME: comment */
399 struct col_ext_type *col_ext_list = NULL;
401 /* Buffer for color sequences */
402 static char *color_buf;
404 /* base used for human style output */
406 static int human_readable_base;
408 /* Nonzero means mention the inode number of each file. -i */
410 static int print_inode;
412 /* Nonzero means when a symbolic link is found, display info on
413 the file linked to. -L */
415 static int trace_links;
417 /* Nonzero means when a directory is found, display info on its
418 contents. -R */
420 static int trace_dirs;
422 /* Nonzero means when an argument is a directory name, display info
423 on it itself. -d */
425 static int immediate_dirs;
427 /* Nonzero means don't omit files whose names start with `.'. -A */
429 static int all_files;
431 /* Nonzero means don't omit files `.' and `..'
432 This flag implies `all_files'. -a */
434 static int really_all_files;
436 /* A linked list of shell-style globbing patterns. If a non-argument
437 file name matches any of these patterns, it is omitted.
438 Controlled by -I. Multiple -I options accumulate.
439 The -B option adds `*~' and `.*~' to this list. */
441 struct ignore_pattern
443 const char *pattern;
444 struct ignore_pattern *next;
447 static struct ignore_pattern *ignore_patterns;
449 /* Nonzero means quote nongraphic chars in file names. -b */
451 static int quote_funny_chars;
453 /* Nonzero means output nongraphic chars in file names as `?'. -q */
455 static int qmark_funny_chars;
457 /* Nonzero means output each file name using C syntax for a string.
458 Always accompanied by `quote_funny_chars'.
459 This mode, together with -x or -C or -m,
460 and without such frills as -F or -s,
461 is guaranteed to make it possible for a program receiving
462 the output to tell exactly what file names are present. -Q */
464 static int quote_as_string;
466 /* Nonzero means use shell style quoting; it is also unambiguous. -e */
468 static int quote_shell;
470 /* The number of chars per hardware tab stop. Setting this to zero
471 inhibits the use of TAB characters for separating columns. -T */
472 static int tabsize;
474 /* Nonzero means we are listing the working directory because no
475 non-option arguments were given. */
477 static int dir_defaulted;
479 /* Nonzero means print each directory name before listing it. */
481 static int print_dir_name;
483 /* The line length to use for breaking lines in many-per-line format.
484 Can be set with -w. */
486 static int line_length;
488 /* If nonzero, the file listing format requires that stat be called on
489 each file. */
491 static int format_needs_stat;
493 /* The exit status to use if we don't get any fatal errors. */
495 static int exit_status;
497 /* If nonzero, display usage information and exit. */
498 static int show_help;
500 /* If nonzero, print the version on standard output and exit. */
501 static int show_version;
503 static struct option const long_options[] =
505 {"all", no_argument, 0, 'a'},
506 {"escape", no_argument, 0, 'b'},
507 {"directory", no_argument, 0, 'd'},
508 {"dired", no_argument, 0, 'D'},
509 {"full-time", no_argument, &full_time, 1},
510 {"human-readable", no_argument, 0, 'h'},
511 {"inode", no_argument, 0, 'i'},
512 {"kilobytes", no_argument, 0, 'k'},
513 {"numeric-uid-gid", no_argument, 0, 'n'},
514 {"no-group", no_argument, 0, 'G'},
515 {"hide-control-chars", no_argument, 0, 'q'},
516 {"reverse", no_argument, 0, 'r'},
517 {"size", no_argument, 0, 's'},
518 {"width", required_argument, 0, 'w'},
519 {"almost-all", no_argument, 0, 'A'},
520 {"ignore-backups", no_argument, 0, 'B'},
521 {"classify", no_argument, 0, 'F'},
522 {"file-type", no_argument, 0, 'F'},
523 {"si", no_argument, 0, 'H'},
524 {"ignore", required_argument, 0, 'I'},
525 {"dereference", no_argument, 0, 'L'},
526 {"literal", no_argument, 0, 'N'},
527 {"quote-name", no_argument, 0, 'Q'},
528 {"quote-shell", no_argument, 0, 'e'},
529 {"recursive", no_argument, 0, 'R'},
530 {"format", required_argument, 0, 12},
531 {"sort", required_argument, 0, 10},
532 {"tabsize", required_argument, 0, 'T'},
533 {"time", required_argument, 0, 11},
534 {"help", no_argument, &show_help, 1},
535 {"version", no_argument, &show_version, 1},
536 {"color", optional_argument, 0, 13},
537 {NULL, 0, NULL, 0}
540 static char const *const format_args[] =
542 "verbose", "long", "commas", "horizontal", "across",
543 "vertical", "single-column", 0
546 static enum format const formats[] =
548 long_format, long_format, with_commas, horizontal, horizontal,
549 many_per_line, one_per_line
552 static char const *const sort_args[] =
554 "none", "time", "size", "extension", "version", 0
557 static enum sort_type const sort_types[] =
559 sort_none, sort_time, sort_size, sort_extension, sort_version
562 static char const *const time_args[] =
564 "atime", "access", "use", "ctime", "status", 0
567 /* This zero-based index is used solely with the --dired option.
568 When that option is in effect, this counter is incremented for each
569 character of output generated by this program so that the beginning
570 and ending indices (in that output) of every file name can be recorded
571 and later output themselves. */
572 static size_t dired_pos;
574 #define PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
576 /* Write S to STREAM and increment DIRED_POS by S_LEN. */
577 #define FPUTS(s, stream, s_len) \
578 do {fputs ((s), (stream)); dired_pos += s_len;} while (0)
580 /* Like FPUTS, but for use when S is a literal string. */
581 #define FPUTS_LITERAL(s, stream) \
582 do {fputs ((s), (stream)); dired_pos += sizeof((s)) - 1;} while (0)
584 #define DIRED_INDENT() \
585 do \
587 /* FIXME: remove the `&& format == long_format' clause. */ \
588 if (dired && format == long_format) \
589 FPUTS_LITERAL (" ", stdout); \
591 while (0)
593 /* With --dired, store pairs of beginning and ending indices of filenames. */
594 static struct obstack dired_obstack;
596 /* With --dired, store pairs of beginning and ending indices of any
597 directory names that appear as headers (just before `total' line)
598 for lists of directory entries. Such directory names are seen when
599 listing hierarchies using -R and when a directory is listed with at
600 least one other command line argument. */
601 static struct obstack subdired_obstack;
603 /* Save the current index on the specified obstack, OBS. */
604 #define PUSH_CURRENT_DIRED_POS(obs) \
605 do \
607 /* FIXME: remove the `&& format == long_format' clause. */ \
608 if (dired && format == long_format) \
609 obstack_grow ((obs), &dired_pos, sizeof (dired_pos)); \
611 while (0)
613 static enum time_type const time_types[] =
615 time_atime, time_atime, time_atime, time_ctime, time_ctime
618 static char const *const color_args[] =
620 /* Note: "no" is a prefix of "none" so we don't include it. */
621 /* force and none are for compatibility with another color-ls version */
622 "always", "yes", "force",
623 "never", "none",
624 "auto", "tty", "if-tty", 0
627 static enum color_type const color_types[] =
629 color_always, color_always, color_always,
630 color_never, color_never,
631 color_if_tty, color_if_tty, color_if_tty
635 /* Information about filling a column. */
636 struct col_info
638 int valid_len;
639 int line_len;
640 int *col_arr;
643 /* Array with information about column filledness. */
644 static struct col_info *col_info;
646 /* Maximum number of columns ever possible for this display. */
647 static int max_idx;
649 /* The minimum width of a colum is 3: 1 character for the name and 2
650 for the separating white space. */
651 #define MIN_COLUMN_WIDTH 3
654 /* Write to standard output the strings PREFIX and STYLE, followed by
655 a space-separated list of the integers stored in OS all on one line. */
657 static void
658 dired_dump_obstack (const char *prefix, const char *style, struct obstack *os)
660 int n_pos;
662 n_pos = obstack_object_size (os) / sizeof (size_t);
663 if (n_pos > 0)
665 int i;
666 size_t *pos;
668 pos = (size_t *) obstack_finish (os);
669 fputs (prefix, stdout);
670 fputs (style, stdout);
671 for (i = 0; i < n_pos; i++)
672 printf (" %d", (int) pos[i]);
673 fputs ("\n", stdout);
678 main (int argc, char **argv)
680 register int i;
681 register struct pending *thispend;
683 program_name = argv[0];
684 setlocale (LC_ALL, "");
685 bindtextdomain (PACKAGE, LOCALEDIR);
686 textdomain (PACKAGE);
688 exit_status = 0;
689 dir_defaulted = 1;
690 print_dir_name = 1;
691 pending_dirs = 0;
692 current_time = time ((time_t *) 0);
694 i = decode_switches (argc, argv);
696 if (show_version)
698 printf ("%s (%s) %s\n",
699 (ls_mode == LS_LS ? "ls"
700 : (ls_mode == LS_MULTI_COL ? "dir" : "vdir")),
701 GNU_PACKAGE, VERSION);
702 close_stdout ();
703 exit (EXIT_SUCCESS);
706 if (show_help)
707 usage (EXIT_SUCCESS);
709 if (print_with_color)
711 parse_ls_color ();
712 prep_non_filename_text ();
715 format_needs_stat = sort_type == sort_time || sort_type == sort_size
716 || format == long_format
717 || trace_links || trace_dirs || indicator_style != none
718 || print_block_size || print_inode || print_with_color;
720 if (dired && format == long_format)
722 obstack_init (&dired_obstack);
723 obstack_init (&subdired_obstack);
726 nfiles = 100;
727 files = (struct fileinfo *) xmalloc (sizeof (struct fileinfo) * nfiles);
728 files_index = 0;
730 clear_files ();
732 if (i < argc)
733 dir_defaulted = 0;
734 for (; i < argc; i++)
736 strip_trailing_slashes (argv[i]);
737 gobble_file (argv[i], 1, "");
740 if (dir_defaulted)
742 if (immediate_dirs)
743 gobble_file (".", 1, "");
744 else
745 queue_directory (".", 0);
748 if (files_index)
750 sort_files ();
751 if (!immediate_dirs)
752 extract_dirs_from_files ("", 0);
753 /* `files_index' might be zero now. */
755 if (files_index)
757 print_current_files ();
758 if (pending_dirs)
759 PUTCHAR ('\n');
761 else if (pending_dirs && pending_dirs->next == 0)
762 print_dir_name = 0;
764 while (pending_dirs)
766 thispend = pending_dirs;
767 pending_dirs = pending_dirs->next;
768 print_dir (thispend->name, thispend->realname);
769 free (thispend->name);
770 if (thispend->realname)
771 free (thispend->realname);
772 free (thispend);
773 print_dir_name = 1;
776 if (dired && format == long_format)
778 const char *quoting_style = (quote_shell ? " -e"
779 : quote_as_string ? " -Q"
780 : quote_funny_chars ? " -b"
781 : " -N");
782 /* No need to free these since we're about to exit. */
783 dired_dump_obstack ("//DIRED//", quoting_style, &dired_obstack);
784 dired_dump_obstack ("//SUBDIRED//", quoting_style, &subdired_obstack);
787 /* Restore default color before exiting */
788 if (print_with_color)
790 put_indicator (&color_indicator[C_LEFT]);
791 put_indicator (&color_indicator[C_RIGHT]);
794 close_stdout ();
795 exit (exit_status);
798 /* Set all the option flags according to the switches specified.
799 Return the index of the first non-option argument. */
801 static int
802 decode_switches (int argc, char **argv)
804 register char *p;
805 int c;
806 int i;
807 long int tmp_long;
809 qmark_funny_chars = 0;
810 quote_funny_chars = 0;
812 /* initialize all switches to default settings */
814 switch (ls_mode)
816 case LS_MULTI_COL:
817 /* This is for the `dir' program. */
818 format = many_per_line;
819 quote_funny_chars = 1;
820 break;
822 case LS_LONG_FORMAT:
823 /* This is for the `vdir' program. */
824 format = long_format;
825 quote_funny_chars = 1;
826 break;
828 case LS_LS:
829 /* This is for the `ls' program. */
830 if (isatty (1))
832 format = many_per_line;
833 qmark_funny_chars = 1;
835 else
837 format = one_per_line;
838 qmark_funny_chars = 0;
840 break;
842 default:
843 abort ();
846 time_type = time_mtime;
847 full_time = 0;
848 sort_type = sort_name;
849 sort_reverse = 0;
850 numeric_ids = 0;
851 print_block_size = 0;
852 output_units = getenv ("POSIXLY_CORRECT") ? 512 : 1024;
853 indicator_style = none;
854 print_inode = 0;
855 trace_links = 0;
856 trace_dirs = 0;
857 immediate_dirs = 0;
858 all_files = 0;
859 really_all_files = 0;
860 ignore_patterns = 0;
861 quote_as_string = 0;
862 quote_shell = 1;
864 if ((p = getenv ("BLOCKSIZE"))
865 && strncmp (p, "HUMAN", sizeof ("HUMAN") - 1) == 0)
866 human_readable_base = 1024;
867 else if (p && strcmp (p, "SI") == 0)
868 human_readable_base = 1000;
870 line_length = 80;
871 if ((p = getenv ("COLUMNS")) && *p)
873 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
874 && 0 < tmp_long && tmp_long <= INT_MAX)
876 line_length = (int) tmp_long;
878 else
880 error (0, 0,
881 _("ignoring invalid width in environment variable COLUMNS: %s"),
886 #ifdef TIOCGWINSZ
888 struct winsize ws;
890 if (ioctl (1, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
891 line_length = ws.ws_col;
893 #endif
895 /* Using the TABSIZE environment variable is not POSIX-approved.
896 Ignore it when POSIXLY_CORRECT is set. */
897 tabsize = 8;
898 if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
900 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
901 && 0 <= tmp_long && tmp_long <= INT_MAX)
903 tabsize = (int) tmp_long;
905 else
907 error (0, 0,
908 _("ignoring invalid tab size in environment variable TABSIZE: %s"),
913 while ((c = getopt_long (argc, argv,
914 "abcdefghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
915 long_options, NULL)) != -1)
917 switch (c)
919 case 0:
920 break;
922 case 'a':
923 all_files = 1;
924 really_all_files = 1;
925 break;
927 case 'b':
928 quote_funny_chars = 1;
929 quote_as_string = 0;
930 quote_shell = 0;
931 qmark_funny_chars = 0;
932 break;
934 case 'c':
935 time_type = time_ctime;
936 sort_type = sort_time;
937 break;
939 case 'd':
940 immediate_dirs = 1;
941 break;
943 case 'e':
944 quote_shell = 1;
945 quote_as_string = 0;
946 quote_funny_chars = 0;
947 qmark_funny_chars = 0;
948 break;
950 case 'f':
951 /* Same as enabling -a -U and disabling -l -s. */
952 all_files = 1;
953 really_all_files = 1;
954 sort_type = sort_none;
955 /* disable -l */
956 if (format == long_format)
957 format = (isatty (1) ? many_per_line : one_per_line);
958 print_block_size = 0; /* disable -s */
959 print_with_color = 0; /* disable --color */
960 break;
962 case 'g':
963 /* No effect. For BSD compatibility. */
964 break;
966 case 'h':
967 human_readable_base = 1024;
968 break;
970 case 'H':
971 human_readable_base = 1000;
972 break;
974 case 'i':
975 print_inode = 1;
976 break;
978 case 'k':
979 output_units = 1024;
980 break;
982 case 'l':
983 format = long_format;
984 break;
986 case 'm':
987 format = with_commas;
988 break;
990 case 'n':
991 numeric_ids = 1;
992 break;
994 case 'o': /* Just like -l, but don't display group info. */
995 format = long_format;
996 inhibit_group = 1;
997 break;
999 case 'p':
1000 indicator_style = not_programs;
1001 break;
1003 case 'q':
1004 qmark_funny_chars = 1;
1005 quote_as_string = 0;
1006 quote_funny_chars = 0;
1007 quote_shell = 0;
1008 break;
1010 case 'r':
1011 sort_reverse = 1;
1012 break;
1014 case 's':
1015 print_block_size = 1;
1016 break;
1018 case 't':
1019 sort_type = sort_time;
1020 break;
1022 case 'u':
1023 sort_type = sort_time;
1024 time_type = time_atime;
1025 break;
1027 case 'v':
1028 sort_type = sort_version;
1029 break;
1031 case 'w':
1032 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1033 || tmp_long <= 0 || tmp_long > INT_MAX)
1034 error (EXIT_FAILURE, 0, _("invalid line width: %s"), optarg);
1035 line_length = (int) tmp_long;
1036 break;
1038 case 'x':
1039 format = horizontal;
1040 break;
1042 case 'A':
1043 really_all_files = 0;
1044 all_files = 1;
1045 break;
1047 case 'B':
1048 add_ignore_pattern ("*~");
1049 add_ignore_pattern (".*~");
1050 break;
1052 case 'C':
1053 format = many_per_line;
1054 break;
1056 case 'D':
1057 dired = 1;
1058 break;
1060 case 'F':
1061 indicator_style = all;
1062 break;
1064 case 'G': /* inhibit display of group info */
1065 inhibit_group = 1;
1066 break;
1068 case 'I':
1069 add_ignore_pattern (optarg);
1070 break;
1072 case 'L':
1073 trace_links = 1;
1074 break;
1076 case 'N':
1077 quote_as_string = 0;
1078 quote_funny_chars = 0;
1079 quote_shell = 0;
1080 qmark_funny_chars = 0;
1081 break;
1083 case 'Q':
1084 quote_as_string = 1;
1085 quote_funny_chars = 1;
1086 quote_shell = 0;
1087 qmark_funny_chars = 0;
1088 break;
1090 case 'R':
1091 trace_dirs = 1;
1092 break;
1094 case 'S':
1095 sort_type = sort_size;
1096 break;
1098 case 'T':
1099 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1100 || tmp_long < 0 || tmp_long > INT_MAX)
1101 error (EXIT_FAILURE, 0, _("invalid tab size: %s"), optarg);
1102 tabsize = (int) tmp_long;
1103 break;
1105 case 'U':
1106 sort_type = sort_none;
1107 break;
1109 case 'X':
1110 sort_type = sort_extension;
1111 break;
1113 case '1':
1114 format = one_per_line;
1115 break;
1117 case 10: /* --sort */
1118 i = argmatch (optarg, sort_args);
1119 if (i < 0)
1121 invalid_arg (_("sort type"), optarg, i);
1122 usage (EXIT_FAILURE);
1124 sort_type = sort_types[i];
1125 break;
1127 case 11: /* --time */
1128 i = argmatch (optarg, time_args);
1129 if (i < 0)
1131 invalid_arg (_("time type"), optarg, i);
1132 usage (EXIT_FAILURE);
1134 time_type = time_types[i];
1135 break;
1137 case 12: /* --format */
1138 i = argmatch (optarg, format_args);
1139 if (i < 0)
1141 invalid_arg (_("format type"), optarg, i);
1142 usage (EXIT_FAILURE);
1144 format = formats[i];
1145 break;
1147 case 13: /* --color */
1148 if (optarg)
1150 i = argmatch (optarg, color_args);
1151 if (i < 0)
1153 invalid_arg (_("colorization criterion"), optarg, i);
1154 usage (EXIT_FAILURE);
1156 i = color_types[i];
1158 else
1160 /* Using --color with no argument is equivalent to using
1161 --color=always. */
1162 i = color_always;
1165 print_with_color = (i == color_always
1166 || (i == color_if_tty
1167 && isatty (STDOUT_FILENO)));
1169 if (print_with_color)
1171 /* Don't use TAB characters in output. Some terminal
1172 emulators can't handle the combination of tabs and
1173 color codes on the same line. */
1174 tabsize = 0;
1176 break;
1178 default:
1179 usage (EXIT_FAILURE);
1183 if (human_readable_base)
1184 output_units = 1;
1186 return optind;
1189 /* Parse a string as part of the LS_COLORS variable; this may involve
1190 decoding all kinds of escape characters. If equals_end is set an
1191 unescaped equal sign ends the string, otherwise only a : or \0
1192 does. Returns the number of characters output, or -1 on failure.
1194 The resulting string is *not* null-terminated, but may contain
1195 embedded nulls.
1197 Note that both dest and src are char **; on return they point to
1198 the first free byte after the array and the character that ended
1199 the input string, respectively. */
1201 static int
1202 get_funky_string (char **dest, const char **src, int equals_end)
1204 int num; /* For numerical codes */
1205 int count; /* Something to count with */
1206 enum {
1207 ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
1208 } state;
1209 const char *p;
1210 char *q;
1212 p = *src; /* We don't want to double-indirect */
1213 q = *dest; /* the whole darn time. */
1215 count = 0; /* No characters counted in yet. */
1216 num = 0;
1218 state = ST_GND; /* Start in ground state. */
1219 while (state < ST_END)
1221 switch (state)
1223 case ST_GND: /* Ground state (no escapes) */
1224 switch (*p)
1226 case ':':
1227 case '\0':
1228 state = ST_END; /* End of string */
1229 break;
1230 case '\\':
1231 state = ST_BACKSLASH; /* Backslash scape sequence */
1232 ++p;
1233 break;
1234 case '^':
1235 state = ST_CARET; /* Caret escape */
1236 ++p;
1237 break;
1238 case '=':
1239 if (equals_end)
1241 state = ST_END; /* End */
1242 break;
1244 /* else fall through */
1245 default:
1246 *(q++) = *(p++);
1247 ++count;
1248 break;
1250 break;
1252 case ST_BACKSLASH: /* Backslash escaped character */
1253 switch (*p)
1255 case '0':
1256 case '1':
1257 case '2':
1258 case '3':
1259 case '4':
1260 case '5':
1261 case '6':
1262 case '7':
1263 state = ST_OCTAL; /* Octal sequence */
1264 num = *p - '0';
1265 break;
1266 case 'x':
1267 case 'X':
1268 state = ST_HEX; /* Hex sequence */
1269 num = 0;
1270 break;
1271 case 'a': /* Bell */
1272 num = 7; /* Not all C compilers know what \a means */
1273 break;
1274 case 'b': /* Backspace */
1275 num = '\b';
1276 break;
1277 case 'e': /* Escape */
1278 num = 27;
1279 break;
1280 case 'f': /* Form feed */
1281 num = '\f';
1282 break;
1283 case 'n': /* Newline */
1284 num = '\n';
1285 break;
1286 case 'r': /* Carriage return */
1287 num = '\r';
1288 break;
1289 case 't': /* Tab */
1290 num = '\t';
1291 break;
1292 case 'v': /* Vtab */
1293 num = '\v';
1294 break;
1295 case '?': /* Delete */
1296 num = 127;
1297 break;
1298 case '_': /* Space */
1299 num = ' ';
1300 break;
1301 case '\0': /* End of string */
1302 state = ST_ERROR; /* Error! */
1303 break;
1304 default: /* Escaped character like \ ^ : = */
1305 num = *p;
1306 break;
1308 if (state == ST_BACKSLASH)
1310 *(q++) = num;
1311 ++count;
1312 state = ST_GND;
1314 ++p;
1315 break;
1317 case ST_OCTAL: /* Octal sequence */
1318 if (*p < '0' || *p > '7')
1320 *(q++) = num;
1321 ++count;
1322 state = ST_GND;
1324 else
1325 num = (num << 3) + (*(p++) - '0');
1326 break;
1328 case ST_HEX: /* Hex sequence */
1329 switch (*p)
1331 case '0':
1332 case '1':
1333 case '2':
1334 case '3':
1335 case '4':
1336 case '5':
1337 case '6':
1338 case '7':
1339 case '8':
1340 case '9':
1341 num = (num << 4) + (*(p++) - '0');
1342 break;
1343 case 'a':
1344 case 'b':
1345 case 'c':
1346 case 'd':
1347 case 'e':
1348 case 'f':
1349 num = (num << 4) + (*(p++) - 'a') + 10;
1350 break;
1351 case 'A':
1352 case 'B':
1353 case 'C':
1354 case 'D':
1355 case 'E':
1356 case 'F':
1357 num = (num << 4) + (*(p++) - 'A') + 10;
1358 break;
1359 default:
1360 *(q++) = num;
1361 ++count;
1362 state = ST_GND;
1363 break;
1365 break;
1367 case ST_CARET: /* Caret escape */
1368 state = ST_GND; /* Should be the next state... */
1369 if (*p >= '@' && *p <= '~')
1371 *(q++) = *(p++) & 037;
1372 ++count;
1374 else if ( *p == '?')
1376 *(q++) = 127;
1377 ++count;
1379 else
1380 state = ST_ERROR;
1381 break;
1383 default:
1384 abort();
1388 *dest = q;
1389 *src = p;
1391 return state == ST_ERROR ? -1 : count;
1394 static void
1395 parse_ls_color (void)
1397 const char *p; /* Pointer to character being parsed */
1398 char *buf; /* color_buf buffer pointer */
1399 int state; /* State of parser */
1400 int ind_no; /* Indicator number */
1401 char label[3]; /* Indicator label */
1402 struct col_ext_type *ext; /* Extension we are working on */
1403 struct col_ext_type *ext2; /* Extra pointer */
1405 if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
1406 return;
1408 ext = NULL;
1409 strcpy (label, "??");
1411 /* This is an overly conservative estimate, but any possible
1412 LS_COLORS string will *not* generate a color_buf longer than
1413 itself, so it is a safe way of allocating a buffer in
1414 advance. */
1415 buf = color_buf = xstrdup (p);
1417 state = 1;
1418 while (state > 0)
1420 switch (state)
1422 case 1: /* First label character */
1423 switch (*p)
1425 case ':':
1426 ++p;
1427 break;
1429 case '*':
1430 /* Allocate new extension block and add to head of
1431 linked list (this way a later definition will
1432 override an earlier one, which can be useful for
1433 having terminal-specific defs override global). */
1435 ext = (struct col_ext_type *)
1436 xmalloc (sizeof (struct col_ext_type));
1437 ext->next = col_ext_list;
1438 col_ext_list = ext;
1440 ++p;
1441 ext->ext.string = buf;
1443 state = (ext->ext.len =
1444 get_funky_string (&buf, &p, 1)) < 0 ? -1 : 4;
1445 break;
1447 case '\0':
1448 state = 0; /* Done! */
1449 break;
1451 default: /* Assume it is file type label */
1452 label[0] = *(p++);
1453 state = 2;
1454 break;
1456 break;
1458 case 2: /* Second label character */
1459 if (*p)
1461 label[1] = *(p++);
1462 state = 3;
1464 else
1465 state = -1; /* Error */
1466 break;
1468 case 3: /* Equal sign after indicator label */
1469 state = -1; /* Assume failure... */
1470 if (*(p++) == '=')/* It *should* be... */
1472 for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
1474 if (STREQ (label, indicator_name[ind_no]))
1476 color_indicator[ind_no].string = buf;
1477 state = ((color_indicator[ind_no].len =
1478 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);
1479 break;
1482 if (state == -1)
1483 error (0, 0, _("unrecognized prefix: %s"), label);
1485 break;
1487 case 4: /* Equal sign after *.ext */
1488 if (*(p++) == '=')
1490 ext->seq.string = buf;
1491 state = (ext->seq.len =
1492 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;
1494 else
1495 state = -1;
1496 break;
1500 if (state < 0)
1502 struct col_ext_type *e;
1504 error (0, 0,
1505 _("unparsable value for LS_COLORS environment variable"));
1506 free (color_buf);
1507 for (e = col_ext_list; e != NULL ; /* empty */)
1509 ext2 = e;
1510 e = e->next;
1511 free (ext2);
1513 print_with_color = 0;
1517 /* Request that the directory named `name' have its contents listed later.
1518 If `realname' is nonzero, it will be used instead of `name' when the
1519 directory name is printed. This allows symbolic links to directories
1520 to be treated as regular directories but still be listed under their
1521 real names. */
1523 static void
1524 queue_directory (const char *name, const char *realname)
1526 struct pending *new;
1528 new = (struct pending *) xmalloc (sizeof (struct pending));
1529 new->next = pending_dirs;
1530 pending_dirs = new;
1531 new->name = xstrdup (name);
1532 if (realname)
1533 new->realname = xstrdup (realname);
1534 else
1535 new->realname = 0;
1538 /* Read directory `name', and list the files in it.
1539 If `realname' is nonzero, print its name instead of `name';
1540 this is used for symbolic links to directories. */
1542 static void
1543 print_dir (const char *name, const char *realname)
1545 register DIR *reading;
1546 register struct dirent *next;
1547 register uintmax_t total_blocks = 0;
1549 errno = 0;
1550 reading = opendir (name);
1551 if (!reading)
1553 error (0, errno, "%s", name);
1554 exit_status = 1;
1555 return;
1558 /* Read the directory entries, and insert the subfiles into the `files'
1559 table. */
1561 clear_files ();
1563 while ((next = readdir (reading)) != NULL)
1564 if (file_interesting (next))
1565 total_blocks += gobble_file (next->d_name, 0, name);
1567 if (CLOSEDIR (reading))
1569 error (0, errno, "%s", name);
1570 exit_status = 1;
1571 /* Don't return; print whatever we got. */
1574 /* Sort the directory contents. */
1575 sort_files ();
1577 /* If any member files are subdirectories, perhaps they should have their
1578 contents listed rather than being mentioned here as files. */
1580 if (trace_dirs)
1581 extract_dirs_from_files (name, 1);
1583 if (print_dir_name)
1585 DIRED_INDENT ();
1586 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1587 dired_pos += quote_filename (stdout, realname ? realname : name);
1588 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1589 FPUTS_LITERAL (":\n", stdout);
1592 if (format == long_format || print_block_size)
1594 const char *p;
1595 char buf[LONGEST_HUMAN_READABLE + 1];
1597 DIRED_INDENT ();
1598 p = _("total");
1599 FPUTS (p, stdout, strlen (p));
1600 PUTCHAR (' ');
1601 p = human_readable (total_blocks, buf, ST_NBLOCKSIZE, output_units,
1602 human_readable_base);
1603 FPUTS (p, stdout, strlen (p));
1604 PUTCHAR ('\n');
1607 if (files_index)
1608 print_current_files ();
1610 if (pending_dirs)
1611 PUTCHAR ('\n');
1614 /* Add `pattern' to the list of patterns for which files that match are
1615 not listed. */
1617 static void
1618 add_ignore_pattern (const char *pattern)
1620 register struct ignore_pattern *ignore;
1622 ignore = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
1623 ignore->pattern = pattern;
1624 /* Add it to the head of the linked list. */
1625 ignore->next = ignore_patterns;
1626 ignore_patterns = ignore;
1629 /* Return nonzero if the file in `next' should be listed. */
1631 static int
1632 file_interesting (const struct dirent *next)
1634 register struct ignore_pattern *ignore;
1636 for (ignore = ignore_patterns; ignore; ignore = ignore->next)
1637 if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
1638 return 0;
1640 if (really_all_files
1641 || next->d_name[0] != '.'
1642 || (all_files
1643 && next->d_name[1] != '\0'
1644 && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
1645 return 1;
1647 return 0;
1650 /* Enter and remove entries in the table `files'. */
1652 /* Empty the table of files. */
1654 static void
1655 clear_files (void)
1657 register int i;
1659 for (i = 0; i < files_index; i++)
1661 free (files[i].name);
1662 if (files[i].linkname)
1663 free (files[i].linkname);
1666 files_index = 0;
1667 block_size_size = 4;
1670 /* Add a file to the current table of files.
1671 Verify that the file exists, and print an error message if it does not.
1672 Return the number of blocks that the file occupies. */
1674 static uintmax_t
1675 gobble_file (const char *name, int explicit_arg, const char *dirname)
1677 register uintmax_t blocks;
1678 register int val;
1679 register char *path;
1681 if (files_index == nfiles)
1683 nfiles *= 2;
1684 files = (struct fileinfo *) xrealloc ((char *) files,
1685 sizeof (*files) * nfiles);
1688 files[files_index].linkname = 0;
1689 files[files_index].linkmode = 0;
1690 files[files_index].linkok = 0;
1692 if (explicit_arg || format_needs_stat)
1694 /* `path' is the absolute pathname of this file. */
1696 if (name[0] == '/' || dirname[0] == 0)
1697 path = (char *) name;
1698 else
1700 path = (char *) alloca (strlen (name) + strlen (dirname) + 2);
1701 attach (path, dirname, name);
1704 if (trace_links)
1706 val = stat (path, &files[files_index].stat);
1707 if (val < 0)
1708 /* Perhaps a symbolically-linked to file doesn't exist; stat
1709 the link instead. */
1710 val = lstat (path, &files[files_index].stat);
1712 else
1713 val = lstat (path, &files[files_index].stat);
1714 if (val < 0)
1716 error (0, errno, "%s", path);
1717 exit_status = 1;
1718 return 0;
1721 #ifdef S_ISLNK
1722 if (S_ISLNK (files[files_index].stat.st_mode)
1723 && (explicit_arg || format == long_format || print_with_color))
1725 char *linkpath;
1726 struct stat linkstats;
1728 get_link_name (path, &files[files_index]);
1729 linkpath = make_link_path (path, files[files_index].linkname);
1731 /* Avoid following symbolic links when possible, ie, when
1732 they won't be traced and when no indicator is needed. */
1733 if (linkpath
1734 && ((explicit_arg && format != long_format)
1735 || indicator_style != none
1736 || print_with_color)
1737 && stat (linkpath, &linkstats) == 0)
1739 files[files_index].linkok = 1;
1741 /* Symbolic links to directories that are mentioned on the
1742 command line are automatically traced if not being
1743 listed as files. */
1744 if (explicit_arg && format != long_format
1745 && S_ISDIR (linkstats.st_mode))
1747 /* Substitute the linked-to directory's name, but
1748 save the real name in `linkname' for printing. */
1749 if (!immediate_dirs)
1751 const char *tempname = name;
1752 name = linkpath;
1753 linkpath = files[files_index].linkname;
1754 files[files_index].linkname = (char *) tempname;
1756 files[files_index].stat = linkstats;
1758 else
1760 /* Get the linked-to file's mode for the filetype indicator
1761 in long listings. */
1762 files[files_index].linkmode = linkstats.st_mode;
1763 files[files_index].linkok = 1;
1766 if (linkpath)
1767 free (linkpath);
1769 #endif
1771 #ifdef S_ISLNK
1772 if (S_ISLNK (files[files_index].stat.st_mode))
1773 files[files_index].filetype = symbolic_link;
1774 else
1775 #endif
1776 if (S_ISDIR (files[files_index].stat.st_mode))
1778 if (explicit_arg && !immediate_dirs)
1779 files[files_index].filetype = arg_directory;
1780 else
1781 files[files_index].filetype = directory;
1783 else
1784 files[files_index].filetype = normal;
1786 blocks = ST_NBLOCKS (files[files_index].stat);
1788 char buf[LONGEST_HUMAN_READABLE + 1];
1789 int len = strlen (human_readable (blocks, buf, ST_NBLOCKSIZE,
1790 output_units, human_readable_base));
1791 if (block_size_size < len)
1792 block_size_size = len < 7 ? len : 7;
1795 else
1796 blocks = 0;
1798 files[files_index].name = xstrdup (name);
1799 files_index++;
1801 return blocks;
1804 #ifdef S_ISLNK
1806 /* Put the name of the file that `filename' is a symbolic link to
1807 into the `linkname' field of `f'. */
1809 static void
1810 get_link_name (const char *filename, struct fileinfo *f)
1812 char *linkbuf;
1813 register int linksize;
1815 linkbuf = (char *) alloca (PATH_MAX + 2);
1816 /* Some automounters give incorrect st_size for mount points.
1817 I can't think of a good workaround for it, though. */
1818 linksize = readlink (filename, linkbuf, PATH_MAX + 1);
1819 if (linksize < 0)
1821 error (0, errno, "%s", filename);
1822 exit_status = 1;
1824 else
1826 linkbuf[linksize] = '\0';
1827 f->linkname = xstrdup (linkbuf);
1831 /* If `linkname' is a relative path and `path' contains one or more
1832 leading directories, return `linkname' with those directories
1833 prepended; otherwise, return a copy of `linkname'.
1834 If `linkname' is zero, return zero. */
1836 static char *
1837 make_link_path (const char *path, const char *linkname)
1839 char *linkbuf;
1840 int bufsiz;
1842 if (linkname == 0)
1843 return 0;
1845 if (*linkname == '/')
1846 return xstrdup (linkname);
1848 /* The link is to a relative path. Prepend any leading path
1849 in `path' to the link name. */
1850 linkbuf = strrchr (path, '/');
1851 if (linkbuf == 0)
1852 return xstrdup (linkname);
1854 bufsiz = linkbuf - path + 1;
1855 linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);
1856 strncpy (linkbuf, path, bufsiz);
1857 strcpy (linkbuf + bufsiz, linkname);
1858 return linkbuf;
1860 #endif
1862 /* Remove any entries from `files' that are for directories,
1863 and queue them to be listed as directories instead.
1864 `dirname' is the prefix to prepend to each dirname
1865 to make it correct relative to ls's working dir.
1866 `recursive' is nonzero if we should not treat `.' and `..' as dirs.
1867 This is desirable when processing directories recursively. */
1869 static void
1870 extract_dirs_from_files (const char *dirname, int recursive)
1872 register int i, j;
1873 register char *path;
1874 int dirlen;
1876 dirlen = strlen (dirname) + 2;
1877 /* Queue the directories last one first, because queueing reverses the
1878 order. */
1879 for (i = files_index - 1; i >= 0; i--)
1880 if ((files[i].filetype == directory || files[i].filetype == arg_directory)
1881 && (!recursive || is_not_dot_or_dotdot (files[i].name)))
1883 if (files[i].name[0] == '/' || dirname[0] == 0)
1885 queue_directory (files[i].name, files[i].linkname);
1887 else
1889 path = (char *) xmalloc (strlen (files[i].name) + dirlen);
1890 attach (path, dirname, files[i].name);
1891 queue_directory (path, files[i].linkname);
1892 free (path);
1894 if (files[i].filetype == arg_directory)
1895 free (files[i].name);
1898 /* Now delete the directories from the table, compacting all the remaining
1899 entries. */
1901 for (i = 0, j = 0; i < files_index; i++)
1902 if (files[i].filetype != arg_directory)
1903 files[j++] = files[i];
1904 files_index = j;
1907 /* Return nonzero if `name' doesn't end in `.' or `..'
1908 This is so we don't try to recurse on `././././. ...' */
1910 static int
1911 is_not_dot_or_dotdot (const char *name)
1913 char *t;
1915 t = strrchr (name, '/');
1916 if (t)
1917 name = t + 1;
1919 if (name[0] == '.'
1920 && (name[1] == '\0'
1921 || (name[1] == '.' && name[2] == '\0')))
1922 return 0;
1924 return 1;
1927 /* Sort the files now in the table. */
1929 static void
1930 sort_files (void)
1932 int (*func) ();
1934 switch (sort_type)
1936 case sort_none:
1937 return;
1938 case sort_time:
1939 switch (time_type)
1941 case time_ctime:
1942 func = sort_reverse ? rev_cmp_ctime : compare_ctime;
1943 break;
1944 case time_mtime:
1945 func = sort_reverse ? rev_cmp_mtime : compare_mtime;
1946 break;
1947 case time_atime:
1948 func = sort_reverse ? rev_cmp_atime : compare_atime;
1949 break;
1950 default:
1951 abort ();
1953 break;
1954 case sort_name:
1955 func = sort_reverse ? rev_cmp_name : compare_name;
1956 break;
1957 case sort_extension:
1958 func = sort_reverse ? rev_cmp_extension : compare_extension;
1959 break;
1960 case sort_size:
1961 func = sort_reverse ? rev_cmp_size : compare_size;
1962 break;
1963 case sort_version:
1964 func = sort_reverse ? rev_cmp_version : compare_version;
1965 break;
1966 default:
1967 abort ();
1970 qsort (files, files_index, sizeof (struct fileinfo), func);
1973 /* Comparison routines for sorting the files. */
1975 static int
1976 compare_ctime (const struct fileinfo *file1, const struct fileinfo *file2)
1978 return longdiff (file2->stat.st_ctime, file1->stat.st_ctime);
1981 static int
1982 rev_cmp_ctime (const struct fileinfo *file2, const struct fileinfo *file1)
1984 return longdiff (file2->stat.st_ctime, file1->stat.st_ctime);
1987 static int
1988 compare_mtime (const struct fileinfo *file1, const struct fileinfo *file2)
1990 return longdiff (file2->stat.st_mtime, file1->stat.st_mtime);
1993 static int
1994 rev_cmp_mtime (const struct fileinfo *file2, const struct fileinfo *file1)
1996 return longdiff (file2->stat.st_mtime, file1->stat.st_mtime);
1999 static int
2000 compare_atime (const struct fileinfo *file1, const struct fileinfo *file2)
2002 return longdiff (file2->stat.st_atime, file1->stat.st_atime);
2005 static int
2006 rev_cmp_atime (const struct fileinfo *file2, const struct fileinfo *file1)
2008 return longdiff (file2->stat.st_atime, file1->stat.st_atime);
2011 static int
2012 compare_size (const struct fileinfo *file1, const struct fileinfo *file2)
2014 return longdiff (file2->stat.st_size, file1->stat.st_size);
2017 static int
2018 rev_cmp_size (const struct fileinfo *file2, const struct fileinfo *file1)
2020 return longdiff (file2->stat.st_size, file1->stat.st_size);
2023 static int
2024 compare_version (const struct fileinfo *file1, const struct fileinfo *file2)
2026 return strverscmp (file1->name, file2->name);
2029 static int
2030 rev_cmp_version (const struct fileinfo *file2, const struct fileinfo *file1)
2032 return strverscmp (file1->name, file2->name);
2035 static int
2036 compare_name (const struct fileinfo *file1, const struct fileinfo *file2)
2038 return strcmp (file1->name, file2->name);
2041 static int
2042 rev_cmp_name (const struct fileinfo *file2, const struct fileinfo *file1)
2044 return strcmp (file1->name, file2->name);
2047 /* Compare file extensions. Files with no extension are `smallest'.
2048 If extensions are the same, compare by filenames instead. */
2050 static int
2051 compare_extension (const struct fileinfo *file1, const struct fileinfo *file2)
2053 register char *base1, *base2;
2054 register int cmp;
2056 base1 = strrchr (file1->name, '.');
2057 base2 = strrchr (file2->name, '.');
2058 if (base1 == 0 && base2 == 0)
2059 return strcmp (file1->name, file2->name);
2060 if (base1 == 0)
2061 return -1;
2062 if (base2 == 0)
2063 return 1;
2064 cmp = strcmp (base1, base2);
2065 if (cmp == 0)
2066 return strcmp (file1->name, file2->name);
2067 return cmp;
2070 static int
2071 rev_cmp_extension (const struct fileinfo *file2, const struct fileinfo *file1)
2073 register char *base1, *base2;
2074 register int cmp;
2076 base1 = strrchr (file1->name, '.');
2077 base2 = strrchr (file2->name, '.');
2078 if (base1 == 0 && base2 == 0)
2079 return strcmp (file1->name, file2->name);
2080 if (base1 == 0)
2081 return -1;
2082 if (base2 == 0)
2083 return 1;
2084 cmp = strcmp (base1, base2);
2085 if (cmp == 0)
2086 return strcmp (file1->name, file2->name);
2087 return cmp;
2090 /* List all the files now in the table. */
2092 static void
2093 print_current_files (void)
2095 register int i;
2097 switch (format)
2099 case one_per_line:
2100 for (i = 0; i < files_index; i++)
2102 print_file_name_and_frills (files + i);
2103 putchar ('\n');
2105 break;
2107 case many_per_line:
2108 init_col_info ();
2109 print_many_per_line ();
2110 break;
2112 case horizontal:
2113 init_col_info ();
2114 print_horizontal ();
2115 break;
2117 case with_commas:
2118 print_with_commas ();
2119 break;
2121 case long_format:
2122 for (i = 0; i < files_index; i++)
2124 print_long_format (files + i);
2125 PUTCHAR ('\n');
2127 break;
2131 static void
2132 print_long_format (const struct fileinfo *f)
2134 char modebuf[11];
2136 /* 7 fields that may require LONGEST_HUMAN_READABLE bytes,
2137 1 10-byte mode string,
2138 1 24-byte time string (may be longer in some locales -- see below)
2139 or LONGEST_HUMAN_READABLE integer,
2140 9 spaces, one following each of these fields, and
2141 1 trailing NUL byte. */
2142 char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10
2143 + (LONGEST_HUMAN_READABLE < 24 ? 24 : LONGEST_HUMAN_READABLE)
2144 + 9 + 1];
2145 char *buf = init_bigbuf;
2146 size_t bufsize = sizeof (init_bigbuf);
2147 size_t s;
2148 char *p;
2149 time_t when;
2150 struct tm *when_local;
2151 const char *fmt;
2152 char *user_name;
2154 #ifdef HAVE_ST_DM_MODE
2155 mode_string (f->stat.st_dm_mode, modebuf);
2156 #else
2157 mode_string (f->stat.st_mode, modebuf);
2158 #endif
2160 modebuf[10] = '\0';
2162 switch (time_type)
2164 case time_ctime:
2165 when = f->stat.st_ctime;
2166 break;
2167 case time_mtime:
2168 when = f->stat.st_mtime;
2169 break;
2170 case time_atime:
2171 when = f->stat.st_atime;
2172 break;
2175 if (full_time)
2177 fmt = "%a %b %d %H:%M:%S %Y";
2179 else
2181 if (current_time > when + 6L * 30L * 24L * 60L * 60L /* Old. */
2182 || current_time < when - 60L * 60L) /* In the future. */
2184 /* The file is fairly old or in the future.
2185 POSIX says the cutoff is 6 months old;
2186 approximate this by 6*30 days.
2187 Allow a 1 hour slop factor for what is considered "the future",
2188 to allow for NFS server/client clock disagreement.
2189 Show the year instead of the time of day. */
2190 fmt = "%b %e %Y";
2192 else
2194 fmt = "%b %e %H:%M";
2198 p = buf;
2200 if (print_inode)
2202 char hbuf[LONGEST_HUMAN_READABLE + 1];
2203 sprintf (p, "%*s ", INODE_DIGITS,
2204 human_readable ((uintmax_t) f->stat.st_ino, hbuf, 1, 1, 0));
2205 p += strlen (p);
2208 if (print_block_size)
2210 char hbuf[LONGEST_HUMAN_READABLE + 1];
2211 sprintf (p, "%*s ", block_size_size,
2212 human_readable ((uintmax_t) ST_NBLOCKS (f->stat), hbuf,
2213 ST_NBLOCKSIZE, output_units,
2214 human_readable_base));
2215 p += strlen (p);
2218 /* The space between the mode and the number of links is the POSIX
2219 "optional alternate access method flag". */
2220 sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink);
2221 p += strlen (p);
2223 user_name = (numeric_ids ? NULL : getuser (f->stat.st_uid));
2224 if (user_name)
2225 sprintf (p, "%-8.8s ", user_name);
2226 else
2227 sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
2228 p += strlen (p);
2230 if (!inhibit_group)
2232 char *group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid));
2233 if (group_name)
2234 sprintf (p, "%-8.8s ", group_name);
2235 else
2236 sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid);
2237 p += strlen (p);
2240 if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
2241 sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
2242 (unsigned) minor (f->stat.st_rdev));
2243 else
2245 char hbuf[LONGEST_HUMAN_READABLE + 1];
2246 sprintf (p, "%8s ",
2247 human_readable ((uintmax_t) f->stat.st_size,
2248 hbuf, 1, 1, human_readable_base));
2251 p += strlen (p);
2253 /* Use strftime rather than ctime, because the former can produce
2254 locale-dependent names for the weekday (%a) and month (%b). */
2256 if ((when_local = localtime (&when)))
2258 while (! (s = strftime (p, buf + bufsize - p - 1, fmt, when_local)))
2260 char *newbuf = (char *) alloca (bufsize *= 2);
2261 memcpy (newbuf, buf, p - buf);
2262 p = newbuf + (p - buf);
2263 buf = newbuf;
2266 p += s;
2267 *p++ = ' ';
2269 /* NUL-terminate the string -- fputs (via FPUTS) requires it. */
2270 *p = '\0';
2272 else
2274 /* The time cannot be represented as a local time;
2275 print it as a huge integer number of seconds. */
2276 char hbuf[LONGEST_HUMAN_READABLE + 1];
2277 int width = full_time ? 24 : 12;
2279 if (when < 0)
2281 const char *num = human_readable (- (uintmax_t) when, hbuf, 1, 1, 0);
2282 int sign_width = width - strlen (num);
2283 sprintf (p, "%*s%s ", sign_width < 0 ? 0 : sign_width, "-", num);
2285 else
2286 sprintf (p, "%*s ", width,
2287 human_readable ((uintmax_t) when, hbuf, 1, 1, 0));
2289 p += strlen (p);
2292 DIRED_INDENT ();
2293 FPUTS (buf, stdout, p - buf);
2294 print_name_with_quoting (f->name, f->stat.st_mode, f->linkok,
2295 &dired_obstack);
2297 if (f->filetype == symbolic_link)
2299 if (f->linkname)
2301 FPUTS_LITERAL (" -> ", stdout);
2302 print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1,
2303 NULL);
2304 if (indicator_style != none)
2305 print_type_indicator (f->linkmode);
2308 else if (indicator_style != none)
2309 print_type_indicator (f->stat.st_mode);
2312 /* If OUT is not null, output a quoted representation of the file name P.
2313 Return the number of characters in P's quoted representation. */
2315 static size_t
2316 quote_filename (register FILE *out, register const char *p)
2318 register unsigned char c;
2319 register size_t len;
2320 #define OUTCHAR(c) do { len++; if (out) putc (c, out); } while (0)
2322 if (quote_shell)
2324 const char *p0 = p;
2326 switch (*p)
2328 case '\0': case '#': case '~':
2329 break;
2331 default:
2332 for (;; p++)
2334 switch (*p)
2336 default:
2337 continue;
2339 case '\t': case '\n': case ' ':
2340 case '!': /* special in csh */
2341 case '"': case '$': case '&': case '\'':
2342 case '(': case ')': case '*': case ';':
2343 case '<': case '>': case '?': case '[': case '\\':
2344 case '^': /* synonym for | in old /bin/sh, e.g. SunOS 4.1.4 */
2345 case '`': case '|':
2346 break;
2348 case '\0':
2349 switch (p[-1])
2351 case '=': case '@':
2352 /* These require quoting if at the end of the file name,
2353 to avoid ambiguity with the output of -F or -p. */
2354 break;
2356 default:
2357 len = p - p0;
2358 if (out)
2359 fwrite (p0, 1, len, out);
2360 return len;
2363 break;
2366 break;
2370 /* Shell quoting is needed. */
2372 p = p0;
2373 len = 0;
2374 OUTCHAR ('\'');
2376 while ((c = *p++))
2378 OUTCHAR (c);
2380 if (c == '\'')
2382 OUTCHAR ('\\');
2383 OUTCHAR ('\'');
2384 OUTCHAR ('\'');
2388 OUTCHAR ('\'');
2390 else
2392 len = 0;
2394 if (quote_as_string)
2395 OUTCHAR ('"');
2397 while ((c = *p++))
2399 if (quote_funny_chars)
2401 switch (c)
2403 case '\\': OUTCHAR ('\\'); break;
2404 case '\n': OUTCHAR ('\\'); c = 'n'; break;
2405 case '\b': OUTCHAR ('\\'); c = 'b'; break;
2406 case '\r': OUTCHAR ('\\'); c = 'r'; break;
2407 case '\t': OUTCHAR ('\\'); c = 't'; break;
2408 case '\f': OUTCHAR ('\\'); c = 'f'; break;
2410 case ' ':
2411 if (!quote_as_string)
2412 OUTCHAR ('\\');
2413 break;
2415 case '"':
2416 if (quote_as_string)
2417 OUTCHAR ('\\');
2418 break;
2420 default:
2421 if (!ISGRAPH (c))
2423 OUTCHAR ('\\');
2424 OUTCHAR ('0' + (c >> 6));
2425 OUTCHAR ('0' + ((c >> 3) & 3));
2426 c = '0' + (c & 3);
2430 else if (qmark_funny_chars && !ISPRINT (c))
2431 c = '?';
2433 OUTCHAR (c);
2436 if (quote_as_string)
2437 OUTCHAR ('"');
2440 return len;
2443 static void
2444 print_name_with_quoting (const char *p, unsigned int mode, int linkok,
2445 struct obstack *stack)
2447 if (print_with_color)
2448 print_color_indicator (p, mode, linkok);
2450 if (stack)
2451 PUSH_CURRENT_DIRED_POS (stack);
2453 dired_pos += quote_filename (stdout, p);
2455 if (stack)
2456 PUSH_CURRENT_DIRED_POS (stack);
2458 if (print_with_color)
2459 prep_non_filename_text ();
2462 static void
2463 prep_non_filename_text (void)
2465 if (color_indicator[C_END].string != NULL)
2466 put_indicator (&color_indicator[C_END]);
2467 else
2469 put_indicator (&color_indicator[C_LEFT]);
2470 put_indicator (&color_indicator[C_NORM]);
2471 put_indicator (&color_indicator[C_RIGHT]);
2475 /* Print the file name of `f' with appropriate quoting.
2476 Also print file size, inode number, and filetype indicator character,
2477 as requested by switches. */
2479 static void
2480 print_file_name_and_frills (const struct fileinfo *f)
2482 char buf[LONGEST_HUMAN_READABLE + 1];
2484 if (print_inode)
2485 printf ("%*s ", INODE_DIGITS,
2486 human_readable ((uintmax_t) f->stat.st_ino, buf, 1, 1, 0));
2488 if (print_block_size)
2489 printf ("%*s ", block_size_size,
2490 human_readable ((uintmax_t) ST_NBLOCKS (f->stat), buf,
2491 ST_NBLOCKSIZE, output_units, human_readable_base));
2493 print_name_with_quoting (f->name, f->stat.st_mode, f->linkok, NULL);
2495 if (indicator_style != none)
2496 print_type_indicator (f->stat.st_mode);
2499 static void
2500 print_type_indicator (unsigned int mode)
2502 if (S_ISDIR (mode))
2503 PUTCHAR ('/');
2505 #ifdef S_ISLNK
2506 if (S_ISLNK (mode))
2507 PUTCHAR ('@');
2508 #endif
2510 #ifdef S_ISFIFO
2511 if (S_ISFIFO (mode))
2512 PUTCHAR ('|');
2513 #endif
2515 #ifdef S_ISSOCK
2516 if (S_ISSOCK (mode))
2517 PUTCHAR ('=');
2518 #endif
2520 if (S_ISREG (mode) && indicator_style == all
2521 && (mode & S_IXUGO))
2522 PUTCHAR ('*');
2525 static void
2526 print_color_indicator (const char *name, unsigned int mode, int linkok)
2528 int type = C_FILE;
2529 struct col_ext_type *ext; /* Color extension */
2530 size_t len; /* Length of name */
2532 /* Is this a nonexistent file? If so, linkok == -1. */
2534 if (linkok == -1 && color_indicator[C_MISSING].string != NULL)
2536 ext = NULL;
2537 type = C_MISSING;
2539 else
2541 if (S_ISDIR (mode))
2542 type = C_DIR;
2544 #ifdef S_ISLNK
2545 else if (S_ISLNK (mode))
2546 type = ((!linkok && color_indicator[C_ORPHAN].string)
2547 ? C_ORPHAN : C_LINK);
2548 #endif
2550 #ifdef S_ISFIFO
2551 else if (S_ISFIFO (mode))
2552 type = C_FIFO;
2553 #endif
2555 #ifdef S_ISSOCK
2556 else if (S_ISSOCK (mode))
2557 type = C_SOCK;
2558 #endif
2560 #ifdef S_ISBLK
2561 else if (S_ISBLK (mode))
2562 type = C_BLK;
2563 #endif
2565 #ifdef S_ISCHR
2566 else if (S_ISCHR (mode))
2567 type = C_CHR;
2568 #endif
2570 if (type == C_FILE && (mode & S_IXUGO) != 0)
2571 type = C_EXEC;
2573 /* Check the file's suffix only if still classified as C_FILE. */
2574 ext = NULL;
2575 if (type == C_FILE)
2577 /* Test if NAME has a recognized suffix. */
2579 len = strlen (name);
2580 name += len; /* Pointer to final \0. */
2581 for (ext = col_ext_list; ext != NULL; ext = ext->next)
2583 if ((size_t) ext->ext.len <= len
2584 && strncmp (name - ext->ext.len, ext->ext.string,
2585 ext->ext.len) == 0)
2586 break;
2591 put_indicator (&color_indicator[C_LEFT]);
2592 put_indicator (ext ? &(ext->seq) : &color_indicator[type]);
2593 put_indicator (&color_indicator[C_RIGHT]);
2596 /* Output a color indicator (which may contain nulls). */
2597 static void
2598 put_indicator (const struct bin_str *ind)
2600 register int i;
2601 register char *p;
2603 p = ind->string;
2605 for (i = ind->len; i > 0; --i)
2606 putchar (*(p++));
2609 static int
2610 length_of_file_name_and_frills (const struct fileinfo *f)
2612 register int len = 0;
2614 if (print_inode)
2615 len += INODE_DIGITS + 1;
2617 if (print_block_size)
2618 len += 1 + block_size_size;
2620 len += quote_filename (0, f->name);
2622 if (indicator_style != none)
2624 unsigned filetype = f->stat.st_mode;
2626 if (S_ISREG (filetype))
2628 if (indicator_style == all
2629 && (f->stat.st_mode & S_IXUGO))
2630 len += 1;
2632 else if (S_ISDIR (filetype)
2633 #ifdef S_ISLNK
2634 || S_ISLNK (filetype)
2635 #endif
2636 #ifdef S_ISFIFO
2637 || S_ISFIFO (filetype)
2638 #endif
2639 #ifdef S_ISSOCK
2640 || S_ISSOCK (filetype)
2641 #endif
2643 len += 1;
2646 return len;
2649 static void
2650 print_many_per_line (void)
2652 struct col_info *line_fmt;
2653 int filesno; /* Index into files. */
2654 int row; /* Current row. */
2655 int max_name_length; /* Length of longest file name + frills. */
2656 int name_length; /* Length of each file name + frills. */
2657 int pos; /* Current character column. */
2658 int cols; /* Number of files across. */
2659 int rows; /* Maximum number of files down. */
2660 int max_cols;
2662 /* Normally the maximum number of columns is determined by the
2663 screen width. But if few files are available this might limit it
2664 as well. */
2665 max_cols = max_idx > files_index ? files_index : max_idx;
2667 /* Compute the maximum number of possible columns. */
2668 for (filesno = 0; filesno < files_index; ++filesno)
2670 int i;
2672 name_length = length_of_file_name_and_frills (files + filesno);
2674 for (i = 0; i < max_cols; ++i)
2676 if (col_info[i].valid_len)
2678 int idx = filesno / ((files_index + i) / (i + 1));
2679 int real_length = name_length + (idx == i ? 0 : 2);
2681 if (real_length > col_info[i].col_arr[idx])
2683 col_info[i].line_len += (real_length
2684 - col_info[i].col_arr[idx]);
2685 col_info[i].col_arr[idx] = real_length;
2686 col_info[i].valid_len = col_info[i].line_len < line_length;
2692 /* Find maximum allowed columns. */
2693 for (cols = max_cols; cols > 1; --cols)
2695 if (col_info[cols - 1].valid_len)
2696 break;
2699 line_fmt = &col_info[cols - 1];
2701 /* Calculate the number of rows that will be in each column except possibly
2702 for a short column on the right. */
2703 rows = files_index / cols + (files_index % cols != 0);
2705 for (row = 0; row < rows; row++)
2707 int col = 0;
2708 filesno = row;
2709 pos = 0;
2710 /* Print the next row. */
2711 while (1)
2713 print_file_name_and_frills (files + filesno);
2714 name_length = length_of_file_name_and_frills (files + filesno);
2715 max_name_length = line_fmt->col_arr[col++];
2717 filesno += rows;
2718 if (filesno >= files_index)
2719 break;
2721 indent (pos + name_length, pos + max_name_length);
2722 pos += max_name_length;
2724 putchar ('\n');
2728 static void
2729 print_horizontal (void)
2731 struct col_info *line_fmt;
2732 int filesno;
2733 int max_name_length;
2734 int name_length;
2735 int cols;
2736 int pos;
2737 int max_cols;
2739 /* Normally the maximum number of columns is determined by the
2740 screen width. But if few files are available this might limit it
2741 as well. */
2742 max_cols = max_idx > files_index ? files_index : max_idx;
2744 /* Compute the maximum file name length. */
2745 max_name_length = 0;
2746 for (filesno = 0; filesno < files_index; ++filesno)
2748 int i;
2750 name_length = length_of_file_name_and_frills (files + filesno);
2752 for (i = 0; i < max_cols; ++i)
2754 if (col_info[i].valid_len)
2756 int idx = filesno % (i + 1);
2757 int real_length = name_length + (idx == i ? 0 : 2);
2759 if (real_length > col_info[i].col_arr[idx])
2761 col_info[i].line_len += (real_length
2762 - col_info[i].col_arr[idx]);
2763 col_info[i].col_arr[idx] = real_length;
2764 col_info[i].valid_len = col_info[i].line_len < line_length;
2770 /* Find maximum allowed columns. */
2771 for (cols = max_cols; cols > 1; --cols)
2773 if (col_info[cols - 1].valid_len)
2774 break;
2777 line_fmt = &col_info[cols - 1];
2779 pos = 0;
2781 /* Print first entry. */
2782 print_file_name_and_frills (files);
2783 name_length = length_of_file_name_and_frills (files);
2784 max_name_length = line_fmt->col_arr[0];
2786 /* Now the rest. */
2787 for (filesno = 1; filesno < files_index; ++filesno)
2789 int col = filesno % cols;
2791 if (col == 0)
2793 putchar ('\n');
2794 pos = 0;
2796 else
2798 indent (pos + name_length, pos + max_name_length);
2799 pos += max_name_length;
2802 print_file_name_and_frills (files + filesno);
2804 name_length = length_of_file_name_and_frills (files + filesno);
2805 max_name_length = line_fmt->col_arr[col];
2807 putchar ('\n');
2810 static void
2811 print_with_commas (void)
2813 int filesno;
2814 int pos, old_pos;
2816 pos = 0;
2818 for (filesno = 0; filesno < files_index; filesno++)
2820 old_pos = pos;
2822 pos += length_of_file_name_and_frills (files + filesno);
2823 if (filesno + 1 < files_index)
2824 pos += 2; /* For the comma and space */
2826 if (old_pos != 0 && pos >= line_length)
2828 putchar ('\n');
2829 pos -= old_pos;
2832 print_file_name_and_frills (files + filesno);
2833 if (filesno + 1 < files_index)
2835 putchar (',');
2836 putchar (' ');
2839 putchar ('\n');
2842 /* Assuming cursor is at position FROM, indent up to position TO.
2843 Use a TAB character instead of two or more spaces whenever possible. */
2845 static void
2846 indent (int from, int to)
2848 while (from < to)
2850 if (tabsize > 0 && to / tabsize > (from + 1) / tabsize)
2852 putchar ('\t');
2853 from += tabsize - from % tabsize;
2855 else
2857 putchar (' ');
2858 from++;
2863 /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */
2865 static void
2866 attach (char *dest, const char *dirname, const char *name)
2868 const char *dirnamep = dirname;
2870 /* Copy dirname if it is not ".". */
2871 if (dirname[0] != '.' || dirname[1] != 0)
2873 while (*dirnamep)
2874 *dest++ = *dirnamep++;
2875 /* Add '/' if `dirname' doesn't already end with it. */
2876 if (dirnamep > dirname && dirnamep[-1] != '/')
2877 *dest++ = '/';
2879 while (*name)
2880 *dest++ = *name++;
2881 *dest = 0;
2884 static void
2885 init_col_info (void)
2887 int i;
2888 int allocate = 0;
2890 max_idx = line_length / MIN_COLUMN_WIDTH;
2891 if (max_idx == 0)
2892 max_idx = 1;
2894 if (col_info == NULL)
2896 col_info = (struct col_info *) xmalloc (max_idx
2897 * sizeof (struct col_info));
2898 allocate = 1;
2901 for (i = 0; i < max_idx; ++i)
2903 int j;
2905 col_info[i].valid_len = 1;
2906 col_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
2908 if (allocate)
2909 col_info[i].col_arr = (int *) xmalloc ((i + 1) * sizeof (int));
2911 for (j = 0; j <= i; ++j)
2912 col_info[i].col_arr[j] = MIN_COLUMN_WIDTH;
2916 static void
2917 usage (int status)
2919 if (status != 0)
2920 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2921 program_name);
2922 else
2924 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
2925 printf (_("\
2926 List information about the FILEs (the current directory by default).\n\
2927 Sort entries alphabetically if none of -cftuSUX nor --sort.\n\
2929 -a, --all do not hide entries starting with .\n\
2930 -A, --almost-all do not list implied . and ..\n\
2931 -b, --escape print octal escapes for nongraphic characters\n\
2932 -B, --ignore-backups do not list implied entries ending with ~\n\
2933 -c sort by change time; with -l: show ctime\n\
2934 -C list entries by columns\n\
2935 --color[=WHEN] control whether color is used to distinguish file\n\
2936 types. WHEN may be `never', `always', or `auto'\n\
2937 -d, --directory list directory entries instead of contents\n\
2938 -D, --dired generate output designed for Emacs' dired mode\n\
2939 -e, --quote-shell quote entry names for shell (default)\n\
2940 -f do not sort, enable -aU, disable -lst\n\
2941 -F, --classify append a character for typing each entry\n\
2942 --format=WORD across -x, commas -m, horizontal -x, long -l,\n\
2943 single-column -1, verbose -l, vertical -C\n\
2944 --full-time list both full date and full time\n"));
2946 printf (_("\
2947 -g (ignored)\n\
2948 -G, --no-group inhibit display of group information\n\
2949 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
2950 -H, --si likewise, but use powers of 1000 not 1024\n\
2951 -i, --inode print index number of each file\n\
2952 -I, --ignore=PATTERN do not list implied entries matching shell PATTERN\n\
2953 -k, --kilobytes use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\
2954 -l use a long listing format\n\
2955 -L, --dereference list entries pointed to by symbolic links\n\
2956 -m fill width with a comma separated list of entries\n\
2957 -n, --numeric-uid-gid list numeric UIDs and GIDs instead of names\n\
2958 -N, --literal print raw entry names (don't treat e.g. control\n\
2959 characters specially)\n\
2960 -o use long listing format without group info\n\
2961 -p append a character for typing each entry\n\
2962 -q, --hide-control-chars print ? instead of non graphic characters\n\
2963 -Q, --quote-name enclose entry names in double quotes\n\
2964 -r, --reverse reverse order while sorting\n\
2965 -R, --recursive list subdirectories recursively\n\
2966 -s, --size print size of each file, in blocks\n"));
2968 printf (_("\
2969 -S sort by file size\n\
2970 --sort=WORD extension -X, none -U, size -S, time -t,\n\
2971 version -v\n\
2972 status -c, time -t, atime -u, access -u, use -u\n\
2973 --time=WORD show time as WORD instead of modification time:\n\
2974 atime, access, use, ctime or status; use\n\
2975 specified time as sort key if --sort=time\n\
2976 -t sort by modification time\n\
2977 -T, --tabsize=COLS assume tab stops at each COLS instead of 8\n\
2978 -u sort by last access time; with -l: show atime\n\
2979 -U do not sort; list entries in directory order\n\
2980 -v sort by version\n\
2981 -w, --width=COLS assume screen width instead of current value\n\
2982 -x list entries by lines instead of by columns\n\
2983 -X sort alphabetically by entry extension\n\
2984 -1 list one file per line\n\
2985 --help display this help and exit\n\
2986 --version output version information and exit\n\
2988 By default, color is not used to distinguish types of files. That is\n\
2989 equivalent to using --color=none. Using the --color option without the\n\
2990 optional WHEN argument is equivalent to using --color=always. With\n\
2991 --color=auto, color codes are output only if standard output is connected\n\
2992 to a terminal (tty).\n\
2993 "));
2994 puts (_("\nReport bugs to <fileutils-bugs@gnu.org>."));
2995 close_stdout ();
2997 exit (status);