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