xref: /freebsd/bin/ls/ls.c (revision 47f884f0)
14b88c807SRodney W. Grimes /*
24b88c807SRodney W. Grimes  * Copyright (c) 1989, 1993, 1994
34b88c807SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
44b88c807SRodney W. Grimes  *
54b88c807SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
64b88c807SRodney W. Grimes  * Michael Fischbein.
74b88c807SRodney W. Grimes  *
84b88c807SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
94b88c807SRodney W. Grimes  * modification, are permitted provided that the following conditions
104b88c807SRodney W. Grimes  * are met:
114b88c807SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
124b88c807SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
134b88c807SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
144b88c807SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
154b88c807SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
164b88c807SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
174b88c807SRodney W. Grimes  *    must display the following acknowledgement:
184b88c807SRodney W. Grimes  *	This product includes software developed by the University of
194b88c807SRodney W. Grimes  *	California, Berkeley and its contributors.
204b88c807SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
214b88c807SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
224b88c807SRodney W. Grimes  *    without specific prior written permission.
234b88c807SRodney W. Grimes  *
244b88c807SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
254b88c807SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264b88c807SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274b88c807SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
284b88c807SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
294b88c807SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
304b88c807SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
314b88c807SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
324b88c807SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334b88c807SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344b88c807SRodney W. Grimes  * SUCH DAMAGE.
354b88c807SRodney W. Grimes  */
364b88c807SRodney W. Grimes 
374b88c807SRodney W. Grimes #ifndef lint
38d46c1a60SSteve Price static const char copyright[] =
394b88c807SRodney W. Grimes "@(#) Copyright (c) 1989, 1993, 1994\n\
404b88c807SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
41febad2fcSSteve Price #endif /* not lint */
42febad2fcSSteve Price 
43febad2fcSSteve Price #ifndef lint
44febad2fcSSteve Price #if 0
45febad2fcSSteve Price static char sccsid[] = "@(#)ls.c	8.5 (Berkeley) 4/2/94";
46febad2fcSSteve Price #else
47d46c1a60SSteve Price static const char rcsid[] =
482a456239SPeter Wemm   "$FreeBSD$";
49febad2fcSSteve Price #endif
504b88c807SRodney W. Grimes #endif /* not lint */
514b88c807SRodney W. Grimes 
524b88c807SRodney W. Grimes #include <sys/types.h>
534b88c807SRodney W. Grimes #include <sys/stat.h>
544b88c807SRodney W. Grimes #include <sys/ioctl.h>
554b88c807SRodney W. Grimes 
564b88c807SRodney W. Grimes #include <dirent.h>
574b88c807SRodney W. Grimes #include <err.h>
584b88c807SRodney W. Grimes #include <errno.h>
594b88c807SRodney W. Grimes #include <fts.h>
60008a4910SSheldon Hearn #include <limits.h>
61008a4910SSheldon Hearn #include <locale.h>
624b88c807SRodney W. Grimes #include <stdio.h>
634b88c807SRodney W. Grimes #include <stdlib.h>
644b88c807SRodney W. Grimes #include <string.h>
654b88c807SRodney W. Grimes #include <unistd.h>
66bd82d8abSAndrey A. Chernov #ifdef COLORLS
67bd82d8abSAndrey A. Chernov #include <termcap.h>
68bd82d8abSAndrey A. Chernov #include <signal.h>
69bd82d8abSAndrey A. Chernov #endif
704b88c807SRodney W. Grimes 
714b88c807SRodney W. Grimes #include "ls.h"
724b88c807SRodney W. Grimes #include "extern.h"
737304f61fSBrian Feldman #include "lomac.h"
744b88c807SRodney W. Grimes 
75008a4910SSheldon Hearn /*
76008a4910SSheldon Hearn  * Upward approximation of the maximum number of characters needed to
77008a4910SSheldon Hearn  * represent a value of integral type t as a string, excluding the
78008a4910SSheldon Hearn  * NUL terminator, with provision for a sign.
79008a4910SSheldon Hearn  */
801f94b779SSheldon Hearn #define	STRBUF_SIZEOF(t)	(1 + CHAR_BIT * sizeof(t) / 3 + 1)
81008a4910SSheldon Hearn 
824b88c807SRodney W. Grimes static void	 display __P((FTSENT *, FTSENT *));
83545f583cSTim Vanderhoek static u_quad_t	 makenines __P((u_long));
844b88c807SRodney W. Grimes static int	 mastercmp __P((const FTSENT **, const FTSENT **));
854b88c807SRodney W. Grimes static void	 traverse __P((int, char **, int));
864b88c807SRodney W. Grimes 
874b88c807SRodney W. Grimes static void (*printfcn) __P((DISPLAY *));
884b88c807SRodney W. Grimes static int (*sortfcn) __P((const FTSENT *, const FTSENT *));
894b88c807SRodney W. Grimes 
904b88c807SRodney W. Grimes long blocksize;			/* block size units */
914b88c807SRodney W. Grimes int termwidth = 80;		/* default terminal width */
924b88c807SRodney W. Grimes 
934b88c807SRodney W. Grimes /* flags */
944b88c807SRodney W. Grimes int f_accesstime;		/* use time of last access */
954b88c807SRodney W. Grimes int f_column;			/* columnated format */
964b88c807SRodney W. Grimes int f_flags;			/* show flags associated with a file */
970e8d1551SJosef Karthauser int f_humanval;			/* show human-readable file sizes */
984b88c807SRodney W. Grimes int f_inode;			/* print inode */
99475727a0SPaul Traina int f_kblocks;			/* print size in kilobytes */
1004b88c807SRodney W. Grimes int f_listdir;			/* list actual directory, not contents */
1014b88c807SRodney W. Grimes int f_listdot;			/* list files beginning with . */
1024b88c807SRodney W. Grimes int f_longform;			/* long listing format */
1034b88c807SRodney W. Grimes int f_nonprint;			/* show unprintables as ? */
1044b88c807SRodney W. Grimes int f_nosort;			/* don't sort output */
105008a4910SSheldon Hearn int f_notabs;			/* don't use tab-separated multi-col output */
106f3a6a64eSSheldon Hearn int f_numericonly;		/* don't convert uid/gid to name */
1077ea30648SDag-Erling Smørgrav int f_octal;			/* show unprintables as \xxx */
1080d86878cSDag-Erling Smørgrav int f_octal_escape;		/* like f_octal but use C escapes if possible */
1094b88c807SRodney W. Grimes int f_recursive;		/* ls subdirectories also */
1104b88c807SRodney W. Grimes int f_reversesort;		/* reverse whatever sort is used */
1114b88c807SRodney W. Grimes int f_sectime;			/* print the real time for all files */
1124b88c807SRodney W. Grimes int f_singlecol;		/* use single column output */
1134b88c807SRodney W. Grimes int f_size;			/* list size in short listing */
1144b88c807SRodney W. Grimes int f_statustime;		/* use time of last mode change */
1154b88c807SRodney W. Grimes int f_timesort;			/* sort by time vice name */
1164b88c807SRodney W. Grimes int f_type;			/* add type character for non-regular files */
117fb5cb208SSteve Price int f_whiteout;			/* show whiteout entries */
1187304f61fSBrian Feldman int f_lomac;			/* show LOMAC attributes */
11974985094SJosef Karthauser #ifdef COLORLS
1203885812cSJosef Karthauser int f_color;			/* add type in color for non-regular files */
1215a890e22SJosef Karthauser 
1225a890e22SJosef Karthauser char *ansi_bgcol;		/* ANSI sequence to set background colour */
1235a890e22SJosef Karthauser char *ansi_fgcol;		/* ANSI sequence to set foreground colour */
1245a890e22SJosef Karthauser char *ansi_coloff;		/* ANSI sequence to reset colours */
125c1499cf6SJosef Karthauser char *attrs_off;		/* ANSI sequence to turn off attributes */
126c1499cf6SJosef Karthauser char *enter_bold;		/* ANSI sequence to set color to bold mode */
12774985094SJosef Karthauser #endif
1284b88c807SRodney W. Grimes 
129fb1000d6SAdam David int rval;
130fb1000d6SAdam David 
1314b88c807SRodney W. Grimes int
1324b88c807SRodney W. Grimes main(argc, argv)
1334b88c807SRodney W. Grimes 	int argc;
1344b88c807SRodney W. Grimes 	char *argv[];
1354b88c807SRodney W. Grimes {
1364b88c807SRodney W. Grimes 	static char dot[] = ".", *dotav[] = {dot, NULL};
1374b88c807SRodney W. Grimes 	struct winsize win;
1384b88c807SRodney W. Grimes 	int ch, fts_options, notused;
1394b88c807SRodney W. Grimes 	char *p;
1405a890e22SJosef Karthauser #ifdef COLORLS
1415a890e22SJosef Karthauser 	char termcapbuf[1024];	/* termcap definition buffer */
1425a890e22SJosef Karthauser 	char tcapbuf[512];	/* capability buffer */
1435a890e22SJosef Karthauser 	char *bp = tcapbuf;
1445a890e22SJosef Karthauser #endif
1455a890e22SJosef Karthauser 
146f5bd01c6SAndrey A. Chernov 	(void)setlocale(LC_ALL, "");
147f5bd01c6SAndrey A. Chernov 
1484b88c807SRodney W. Grimes 	/* Terminal defaults to -Cq, non-terminal defaults to -1. */
1494b88c807SRodney W. Grimes 	if (isatty(STDOUT_FILENO)) {
1504b88c807SRodney W. Grimes 		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == -1 ||
1514b88c807SRodney W. Grimes 		    !win.ws_col) {
1524b88c807SRodney W. Grimes 			if ((p = getenv("COLUMNS")) != NULL)
1534b88c807SRodney W. Grimes 				termwidth = atoi(p);
1545dda5d0dSJosef Karthauser 		} else
1554b88c807SRodney W. Grimes 			termwidth = win.ws_col;
1564b88c807SRodney W. Grimes 		f_column = f_nonprint = 1;
15734994fcdSJoerg Wunsch 	} else {
1584b88c807SRodney W. Grimes 		f_singlecol = 1;
15934994fcdSJoerg Wunsch 		/* retrieve environment variable, in case of explicit -C */
1600fd510b7SJoerg Wunsch 		if ((p = getenv("COLUMNS")))
16134994fcdSJoerg Wunsch 			termwidth = atoi(p);
16234994fcdSJoerg Wunsch 	}
1634b88c807SRodney W. Grimes 
1644b88c807SRodney W. Grimes 	/* Root is -A automatically. */
1654b88c807SRodney W. Grimes 	if (!getuid())
1664b88c807SRodney W. Grimes 		f_listdot = 1;
1674b88c807SRodney W. Grimes 
1684b88c807SRodney W. Grimes 	fts_options = FTS_PHYSICAL;
16947f884f0SJosef Karthauser  	while ((ch = getopt(argc, argv, "1ABCFGHLPRTWZabcdfghiklnoqrstuw")) != -1) {
1704b88c807SRodney W. Grimes 		switch (ch) {
1714b88c807SRodney W. Grimes 		/*
1724b88c807SRodney W. Grimes 		 * The -1, -C and -l options all override each other so shell
1734b88c807SRodney W. Grimes 		 * aliasing works right.
1744b88c807SRodney W. Grimes 		 */
1754b88c807SRodney W. Grimes 		case '1':
1764b88c807SRodney W. Grimes 			f_singlecol = 1;
1774b88c807SRodney W. Grimes 			f_column = f_longform = 0;
1784b88c807SRodney W. Grimes 			break;
1790d86878cSDag-Erling Smørgrav 		case 'B':
1800d86878cSDag-Erling Smørgrav 			f_nonprint = 0;
1810d86878cSDag-Erling Smørgrav 			f_octal = 1;
1820d86878cSDag-Erling Smørgrav 			f_octal_escape = 0;
1830d86878cSDag-Erling Smørgrav 			break;
1844b88c807SRodney W. Grimes 		case 'C':
1854b88c807SRodney W. Grimes 			f_column = 1;
1864b88c807SRodney W. Grimes 			f_longform = f_singlecol = 0;
1874b88c807SRodney W. Grimes 			break;
1884b88c807SRodney W. Grimes 		case 'l':
1894b88c807SRodney W. Grimes 			f_longform = 1;
1904b88c807SRodney W. Grimes 			f_column = f_singlecol = 0;
1914b88c807SRodney W. Grimes 			break;
1924b88c807SRodney W. Grimes 		/* The -c and -u options override each other. */
1934b88c807SRodney W. Grimes 		case 'c':
1944b88c807SRodney W. Grimes 			f_statustime = 1;
1954b88c807SRodney W. Grimes 			f_accesstime = 0;
1964b88c807SRodney W. Grimes 			break;
1974b88c807SRodney W. Grimes 		case 'u':
1984b88c807SRodney W. Grimes 			f_accesstime = 1;
1994b88c807SRodney W. Grimes 			f_statustime = 0;
2004b88c807SRodney W. Grimes 			break;
2014b88c807SRodney W. Grimes 		case 'F':
2024b88c807SRodney W. Grimes 			f_type = 1;
2034b88c807SRodney W. Grimes 			break;
2043a34dbf7SDag-Erling Smørgrav 		case 'H':
2053a34dbf7SDag-Erling Smørgrav 			fts_options |= FTS_COMFOLLOW;
2063a34dbf7SDag-Erling Smørgrav 			break;
2073885812cSJosef Karthauser 		case 'G':
2083d2ddc9eSJosef Karthauser 			setenv("CLICOLOR", "", 1);
2093885812cSJosef Karthauser 			break;
2104b88c807SRodney W. Grimes 		case 'L':
2114b88c807SRodney W. Grimes 			fts_options &= ~FTS_PHYSICAL;
2124b88c807SRodney W. Grimes 			fts_options |= FTS_LOGICAL;
2134b88c807SRodney W. Grimes 			break;
2143a34dbf7SDag-Erling Smørgrav 		case 'P':
2153a34dbf7SDag-Erling Smørgrav 			fts_options &= ~FTS_COMFOLLOW;
2163a34dbf7SDag-Erling Smørgrav 			fts_options &= ~FTS_LOGICAL;
2173a34dbf7SDag-Erling Smørgrav 			fts_options |= FTS_PHYSICAL;
2183a34dbf7SDag-Erling Smørgrav 			break;
2194b88c807SRodney W. Grimes 		case 'R':
2204b88c807SRodney W. Grimes 			f_recursive = 1;
2214b88c807SRodney W. Grimes 			break;
2224b88c807SRodney W. Grimes 		case 'a':
2234b88c807SRodney W. Grimes 			fts_options |= FTS_SEEDOT;
2244b88c807SRodney W. Grimes 			/* FALLTHROUGH */
2254b88c807SRodney W. Grimes 		case 'A':
2264b88c807SRodney W. Grimes 			f_listdot = 1;
2274b88c807SRodney W. Grimes 			break;
2284b88c807SRodney W. Grimes 		/* The -d option turns off the -R option. */
2294b88c807SRodney W. Grimes 		case 'd':
2304b88c807SRodney W. Grimes 			f_listdir = 1;
2314b88c807SRodney W. Grimes 			f_recursive = 0;
2324b88c807SRodney W. Grimes 			break;
2334b88c807SRodney W. Grimes 		case 'f':
2344b88c807SRodney W. Grimes 			f_nosort = 1;
2354b88c807SRodney W. Grimes 			break;
2364b88c807SRodney W. Grimes 		case 'g':	/* Compatibility with 4.3BSD. */
2374b88c807SRodney W. Grimes 			break;
2380e8d1551SJosef Karthauser 		case 'h':
2390e8d1551SJosef Karthauser 			f_humanval = 1;
2400e8d1551SJosef Karthauser 			break;
2414b88c807SRodney W. Grimes 		case 'i':
2424b88c807SRodney W. Grimes 			f_inode = 1;
2434b88c807SRodney W. Grimes 			break;
244475727a0SPaul Traina 		case 'k':
245475727a0SPaul Traina 			f_kblocks = 1;
246475727a0SPaul Traina 			break;
247f3a6a64eSSheldon Hearn 		case 'n':
248f3a6a64eSSheldon Hearn 			f_numericonly = 1;
249f3a6a64eSSheldon Hearn 			break;
2504b88c807SRodney W. Grimes 		case 'o':
2514b88c807SRodney W. Grimes 			f_flags = 1;
2524b88c807SRodney W. Grimes 			break;
2534b88c807SRodney W. Grimes 		case 'q':
2544b88c807SRodney W. Grimes 			f_nonprint = 1;
2557ea30648SDag-Erling Smørgrav 			f_octal = 0;
2560d86878cSDag-Erling Smørgrav 			f_octal_escape = 0;
2574b88c807SRodney W. Grimes 			break;
2584b88c807SRodney W. Grimes 		case 'r':
2594b88c807SRodney W. Grimes 			f_reversesort = 1;
2604b88c807SRodney W. Grimes 			break;
2614b88c807SRodney W. Grimes 		case 's':
2624b88c807SRodney W. Grimes 			f_size = 1;
2634b88c807SRodney W. Grimes 			break;
2644b88c807SRodney W. Grimes 		case 'T':
2654b88c807SRodney W. Grimes 			f_sectime = 1;
2664b88c807SRodney W. Grimes 			break;
2674b88c807SRodney W. Grimes 		case 't':
2684b88c807SRodney W. Grimes 			f_timesort = 1;
2694b88c807SRodney W. Grimes 			break;
270fb5cb208SSteve Price 		case 'W':
271fb5cb208SSteve Price 			f_whiteout = 1;
272fb5cb208SSteve Price 			break;
2737ea30648SDag-Erling Smørgrav 		case 'b':
2747ea30648SDag-Erling Smørgrav 			f_nonprint = 0;
2750d86878cSDag-Erling Smørgrav 			f_octal = 0;
2760d86878cSDag-Erling Smørgrav 			f_octal_escape = 1;
2777ea30648SDag-Erling Smørgrav 			break;
27847f884f0SJosef Karthauser 		case 'w':
27947f884f0SJosef Karthauser 			f_nonprint = 0;
28047f884f0SJosef Karthauser 			f_octal = 0;
28147f884f0SJosef Karthauser 			f_octal_escape = 0;
28247f884f0SJosef Karthauser 			break;
2837304f61fSBrian Feldman 		case 'Z':
2847304f61fSBrian Feldman 			f_lomac = 1;
2857304f61fSBrian Feldman 			break;
2864b88c807SRodney W. Grimes 		default:
2874b88c807SRodney W. Grimes 		case '?':
2884b88c807SRodney W. Grimes 			usage();
2894b88c807SRodney W. Grimes 		}
2904b88c807SRodney W. Grimes 	}
2914b88c807SRodney W. Grimes 	argc -= optind;
2924b88c807SRodney W. Grimes 	argv += optind;
2934b88c807SRodney W. Grimes 
2943d2ddc9eSJosef Karthauser 	/* Enabling of colours is conditional on the environment. */
2953d2ddc9eSJosef Karthauser 	if (getenv("CLICOLOR") &&
2963d2ddc9eSJosef Karthauser 	    (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE")))
297d4413063SJosef Karthauser #ifdef COLORLS
2983d2ddc9eSJosef Karthauser 		if (tgetent(termcapbuf, getenv("TERM")) == 1) {
2993d2ddc9eSJosef Karthauser 			ansi_fgcol = tgetstr("AF", &bp);
3003d2ddc9eSJosef Karthauser 			ansi_bgcol = tgetstr("AB", &bp);
301c1499cf6SJosef Karthauser 			attrs_off = tgetstr("me", &bp);
302c1499cf6SJosef Karthauser 			enter_bold = tgetstr("md", &bp);
3033d2ddc9eSJosef Karthauser 
3043d2ddc9eSJosef Karthauser 			/* To switch colours off use 'op' if
3053d2ddc9eSJosef Karthauser 			 * available, otherwise use 'oc', or
3063d2ddc9eSJosef Karthauser 			 * don't do colours at all. */
3073d2ddc9eSJosef Karthauser 			ansi_coloff = tgetstr("op", &bp);
3083d2ddc9eSJosef Karthauser 			if (!ansi_coloff)
3093d2ddc9eSJosef Karthauser 				ansi_coloff = tgetstr("oc", &bp);
3103d2ddc9eSJosef Karthauser 			if (ansi_fgcol && ansi_bgcol && ansi_coloff)
3113d2ddc9eSJosef Karthauser 				f_color = 1;
3123d2ddc9eSJosef Karthauser 		}
313d4413063SJosef Karthauser #else
314d4413063SJosef Karthauser 		(void)fprintf(stderr, "Color support not compiled in.\n");
315d4413063SJosef Karthauser #endif /*COLORLS*/
3163d2ddc9eSJosef Karthauser 
317d4413063SJosef Karthauser #ifdef COLORLS
318bd82d8abSAndrey A. Chernov 	if (f_color) {
31922ff3e9eSAndrey A. Chernov 		/*
32022ff3e9eSAndrey A. Chernov 		 * We can't put tabs and color sequences together:
32122ff3e9eSAndrey A. Chernov 		 * column number will be incremented incorrectly
32222ff3e9eSAndrey A. Chernov 		 * for "stty oxtabs" mode.
32322ff3e9eSAndrey A. Chernov 		 */
32422ff3e9eSAndrey A. Chernov 		f_notabs = 1;
325bd82d8abSAndrey A. Chernov 		(void)signal(SIGINT, colorquit);
326ab08444fSMartin Cracauer 		(void)signal(SIGQUIT, colorquit);
3273885812cSJosef Karthauser 		parsecolors(getenv("LSCOLORS"));
328bd82d8abSAndrey A. Chernov 	}
32974985094SJosef Karthauser #endif
3303885812cSJosef Karthauser 
3314b88c807SRodney W. Grimes 	/*
3324b88c807SRodney W. Grimes 	 * If not -F, -i, -l, -s or -t options, don't require stat
3333885812cSJosef Karthauser 	 * information, unless in color mode in which case we do
3343885812cSJosef Karthauser 	 * need this to determine which colors to display.
3354b88c807SRodney W. Grimes 	 */
3363885812cSJosef Karthauser 	if (!f_inode && !f_longform && !f_size && !f_timesort && !f_type
33774985094SJosef Karthauser #ifdef COLORLS
33874985094SJosef Karthauser 	    && !f_color
33974985094SJosef Karthauser #endif
34074985094SJosef Karthauser 	    )
3414b88c807SRodney W. Grimes 		fts_options |= FTS_NOSTAT;
3424b88c807SRodney W. Grimes 
3434b88c807SRodney W. Grimes 	/*
3444b88c807SRodney W. Grimes 	 * If not -F, -d or -l options, follow any symbolic links listed on
3454b88c807SRodney W. Grimes 	 * the command line.
3464b88c807SRodney W. Grimes 	 */
3474b88c807SRodney W. Grimes 	if (!f_longform && !f_listdir && !f_type)
3484b88c807SRodney W. Grimes 		fts_options |= FTS_COMFOLLOW;
3494b88c807SRodney W. Grimes 
350fb5cb208SSteve Price 	/*
351fb5cb208SSteve Price 	 * If -W, show whiteout entries
352fb5cb208SSteve Price 	 */
353fb5cb208SSteve Price #ifdef FTS_WHITEOUT
354fb5cb208SSteve Price 	if (f_whiteout)
355fb5cb208SSteve Price 		fts_options |= FTS_WHITEOUT;
356fb5cb208SSteve Price #endif
357fb5cb208SSteve Price 
3584b88c807SRodney W. Grimes 	/* If -l or -s, figure out block size. */
3594b88c807SRodney W. Grimes 	if (f_longform || f_size) {
36090b0ec31SPoul-Henning Kamp 		if (f_kblocks)
36190b0ec31SPoul-Henning Kamp 			blocksize = 2;
36290b0ec31SPoul-Henning Kamp 		else {
3634b88c807SRodney W. Grimes 			(void)getbsize(&notused, &blocksize);
3644b88c807SRodney W. Grimes 			blocksize /= 512;
36590b0ec31SPoul-Henning Kamp 		}
3664b88c807SRodney W. Grimes 	}
3674b88c807SRodney W. Grimes 	/* Select a sort function. */
3684b88c807SRodney W. Grimes 	if (f_reversesort) {
3694b88c807SRodney W. Grimes 		if (!f_timesort)
3704b88c807SRodney W. Grimes 			sortfcn = revnamecmp;
3714b88c807SRodney W. Grimes 		else if (f_accesstime)
3724b88c807SRodney W. Grimes 			sortfcn = revacccmp;
3734b88c807SRodney W. Grimes 		else if (f_statustime)
3744b88c807SRodney W. Grimes 			sortfcn = revstatcmp;
3754b88c807SRodney W. Grimes 		else		/* Use modification time. */
3764b88c807SRodney W. Grimes 			sortfcn = revmodcmp;
3774b88c807SRodney W. Grimes 	} else {
3784b88c807SRodney W. Grimes 		if (!f_timesort)
3794b88c807SRodney W. Grimes 			sortfcn = namecmp;
3804b88c807SRodney W. Grimes 		else if (f_accesstime)
3814b88c807SRodney W. Grimes 			sortfcn = acccmp;
3824b88c807SRodney W. Grimes 		else if (f_statustime)
3834b88c807SRodney W. Grimes 			sortfcn = statcmp;
3844b88c807SRodney W. Grimes 		else		/* Use modification time. */
3854b88c807SRodney W. Grimes 			sortfcn = modcmp;
3864b88c807SRodney W. Grimes 	}
3874b88c807SRodney W. Grimes 
3884b88c807SRodney W. Grimes 	/* Select a print function. */
3894b88c807SRodney W. Grimes 	if (f_singlecol)
3904b88c807SRodney W. Grimes 		printfcn = printscol;
3914b88c807SRodney W. Grimes 	else if (f_longform)
3924b88c807SRodney W. Grimes 		printfcn = printlong;
3934b88c807SRodney W. Grimes 	else
3944b88c807SRodney W. Grimes 		printfcn = printcol;
3954b88c807SRodney W. Grimes 
3964b88c807SRodney W. Grimes 	if (argc)
3974b88c807SRodney W. Grimes 		traverse(argc, argv, fts_options);
3984b88c807SRodney W. Grimes 	else
3994b88c807SRodney W. Grimes 		traverse(1, dotav, fts_options);
400fb1000d6SAdam David 	exit(rval);
4014b88c807SRodney W. Grimes }
4024b88c807SRodney W. Grimes 
4034b88c807SRodney W. Grimes static int output;		/* If anything output. */
4044b88c807SRodney W. Grimes 
4054b88c807SRodney W. Grimes /*
4064b88c807SRodney W. Grimes  * Traverse() walks the logical directory structure specified by the argv list
4074b88c807SRodney W. Grimes  * in the order specified by the mastercmp() comparison function.  During the
4084b88c807SRodney W. Grimes  * traversal it passes linked lists of structures to display() which represent
4094b88c807SRodney W. Grimes  * a superset (may be exact set) of the files to be displayed.
4104b88c807SRodney W. Grimes  */
4114b88c807SRodney W. Grimes static void
4124b88c807SRodney W. Grimes traverse(argc, argv, options)
4134b88c807SRodney W. Grimes 	int argc, options;
4144b88c807SRodney W. Grimes 	char *argv[];
4154b88c807SRodney W. Grimes {
4164b88c807SRodney W. Grimes 	FTS *ftsp;
4174b88c807SRodney W. Grimes 	FTSENT *p, *chp;
4184b88c807SRodney W. Grimes 	int ch_options;
4194b88c807SRodney W. Grimes 
4204b88c807SRodney W. Grimes 	if ((ftsp =
4214b88c807SRodney W. Grimes 	    fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
4224b88c807SRodney W. Grimes 		err(1, NULL);
4234b88c807SRodney W. Grimes 
4244b88c807SRodney W. Grimes 	display(NULL, fts_children(ftsp, 0));
4254b88c807SRodney W. Grimes 	if (f_listdir)
4264b88c807SRodney W. Grimes 		return;
4274b88c807SRodney W. Grimes 
4284b88c807SRodney W. Grimes 	/*
4294b88c807SRodney W. Grimes 	 * If not recursing down this tree and don't need stat info, just get
4304b88c807SRodney W. Grimes 	 * the names.
4314b88c807SRodney W. Grimes 	 */
4324b88c807SRodney W. Grimes 	ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;
4334b88c807SRodney W. Grimes 
4344b88c807SRodney W. Grimes 	while ((p = fts_read(ftsp)) != NULL)
4354b88c807SRodney W. Grimes 		switch (p->fts_info) {
4364b88c807SRodney W. Grimes 		case FTS_DC:
4374b88c807SRodney W. Grimes 			warnx("%s: directory causes a cycle", p->fts_name);
4384b88c807SRodney W. Grimes 			break;
4394b88c807SRodney W. Grimes 		case FTS_DNR:
4404b88c807SRodney W. Grimes 		case FTS_ERR:
4414b88c807SRodney W. Grimes 			warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
442fb1000d6SAdam David 			rval = 1;
4434b88c807SRodney W. Grimes 			break;
4444b88c807SRodney W. Grimes 		case FTS_D:
4454b88c807SRodney W. Grimes 			if (p->fts_level != FTS_ROOTLEVEL &&
4464b88c807SRodney W. Grimes 			    p->fts_name[0] == '.' && !f_listdot)
4474b88c807SRodney W. Grimes 				break;
4484b88c807SRodney W. Grimes 
4494b88c807SRodney W. Grimes 			/*
4504b88c807SRodney W. Grimes 			 * If already output something, put out a newline as
4514b88c807SRodney W. Grimes 			 * a separator.  If multiple arguments, precede each
4524b88c807SRodney W. Grimes 			 * directory with its name.
4534b88c807SRodney W. Grimes 			 */
4544b88c807SRodney W. Grimes 			if (output)
4554b88c807SRodney W. Grimes 				(void)printf("\n%s:\n", p->fts_path);
4564b88c807SRodney W. Grimes 			else if (argc > 1) {
4574b88c807SRodney W. Grimes 				(void)printf("%s:\n", p->fts_path);
4584b88c807SRodney W. Grimes 				output = 1;
4594b88c807SRodney W. Grimes 			}
4604b88c807SRodney W. Grimes 			chp = fts_children(ftsp, ch_options);
4614b88c807SRodney W. Grimes 			display(p, chp);
4624b88c807SRodney W. Grimes 
4634b88c807SRodney W. Grimes 			if (!f_recursive && chp != NULL)
4644b88c807SRodney W. Grimes 				(void)fts_set(ftsp, p, FTS_SKIP);
4654b88c807SRodney W. Grimes 			break;
4664b88c807SRodney W. Grimes 		}
4674b88c807SRodney W. Grimes 	if (errno)
4684b88c807SRodney W. Grimes 		err(1, "fts_read");
4694b88c807SRodney W. Grimes }
4704b88c807SRodney W. Grimes 
4714b88c807SRodney W. Grimes /*
4724b88c807SRodney W. Grimes  * Display() takes a linked list of FTSENT structures and passes the list
4734b88c807SRodney W. Grimes  * along with any other necessary information to the print function.  P
4744b88c807SRodney W. Grimes  * points to the parent directory of the display list.
4754b88c807SRodney W. Grimes  */
4764b88c807SRodney W. Grimes static void
4774b88c807SRodney W. Grimes display(p, list)
4784b88c807SRodney W. Grimes 	FTSENT *p, *list;
4794b88c807SRodney W. Grimes {
4804b88c807SRodney W. Grimes 	struct stat *sp;
4814b88c807SRodney W. Grimes 	DISPLAY d;
4824b88c807SRodney W. Grimes 	FTSENT *cur;
4834b88c807SRodney W. Grimes 	NAMES *np;
4844b88c807SRodney W. Grimes 	u_quad_t maxsize;
4857304f61fSBrian Feldman 	u_long btotal, maxblock, maxinode, maxlen, maxnlink, maxlattr;
4867304f61fSBrian Feldman 	int bcfile, flen, glen, ulen, lattrlen, maxflags, maxgroup, maxuser;
487545f583cSTim Vanderhoek 	char *initmax;
4884b88c807SRodney W. Grimes 	int entries, needstats;
4897304f61fSBrian Feldman 	char *user, *group, *flags, *lattr;
490008a4910SSheldon Hearn 	char buf[STRBUF_SIZEOF(u_quad_t) + 1];
491008a4910SSheldon Hearn 	char ngroup[STRBUF_SIZEOF(uid_t) + 1];
492008a4910SSheldon Hearn 	char nuser[STRBUF_SIZEOF(gid_t) + 1];
4934b88c807SRodney W. Grimes 
4944b88c807SRodney W. Grimes 	/*
4954b88c807SRodney W. Grimes 	 * If list is NULL there are two possibilities: that the parent
4964b88c807SRodney W. Grimes 	 * directory p has no children, or that fts_children() returned an
4974b88c807SRodney W. Grimes 	 * error.  We ignore the error case since it will be replicated
4984b88c807SRodney W. Grimes 	 * on the next call to fts_read() on the post-order visit to the
49946be34b9SKris Kennaway 	 * directory p, and will be signaled in traverse().
5004b88c807SRodney W. Grimes 	 */
5014b88c807SRodney W. Grimes 	if (list == NULL)
5024b88c807SRodney W. Grimes 		return;
5034b88c807SRodney W. Grimes 
5044b88c807SRodney W. Grimes 	needstats = f_inode || f_longform || f_size;
5054b88c807SRodney W. Grimes 	flen = 0;
506545f583cSTim Vanderhoek 	btotal = 0;
507545f583cSTim Vanderhoek 	initmax = getenv("LS_COLWIDTHS");
508545f583cSTim Vanderhoek 	/* Fields match -lios order.  New ones should be added at the end. */
509545f583cSTim Vanderhoek 	if (initmax != NULL && *initmax != '\0') {
510545f583cSTim Vanderhoek 		char *initmax2, *jinitmax;
511545f583cSTim Vanderhoek 		int ninitmax;
512545f583cSTim Vanderhoek 
513545f583cSTim Vanderhoek 		/* Fill-in "::" as "0:0:0" for the sake of scanf. */
514545f583cSTim Vanderhoek 		jinitmax = initmax2 = malloc(strlen(initmax) * 2 + 2);
515545f583cSTim Vanderhoek 		if (jinitmax == NULL)
516545f583cSTim Vanderhoek 			err(1, NULL);
517545f583cSTim Vanderhoek 		if (*initmax == ':')
518545f583cSTim Vanderhoek 			strcpy(initmax2, "0:"), initmax2 += 2;
519545f583cSTim Vanderhoek 		else
520545f583cSTim Vanderhoek 			*initmax2++ = *initmax, *initmax2 = '\0';
521545f583cSTim Vanderhoek 		for (initmax++; *initmax != '\0'; initmax++) {
522545f583cSTim Vanderhoek 			if (initmax[-1] == ':' && initmax[0] == ':') {
523545f583cSTim Vanderhoek 				*initmax2++ = '0';
524545f583cSTim Vanderhoek 				*initmax2++ = initmax[0];
525545f583cSTim Vanderhoek 				initmax2[1] = '\0';
526545f583cSTim Vanderhoek 			} else {
527545f583cSTim Vanderhoek 				*initmax2++ = initmax[0];
528545f583cSTim Vanderhoek 				initmax2[1] = '\0';
529545f583cSTim Vanderhoek 			}
530545f583cSTim Vanderhoek 		}
5315dda5d0dSJosef Karthauser 		if (initmax2[-1] == ':')
5325dda5d0dSJosef Karthauser 			strcpy(initmax2, "0");
533545f583cSTim Vanderhoek 
534545f583cSTim Vanderhoek 		ninitmax = sscanf(jinitmax,
5357304f61fSBrian Feldman 		    " %lu : %lu : %lu : %i : %i : %i : %qu : %lu : %lu ",
536545f583cSTim Vanderhoek 		    &maxinode, &maxblock, &maxnlink, &maxuser,
5377304f61fSBrian Feldman 		    &maxgroup, &maxflags, &maxsize, &maxlen, &maxlattr);
538545f583cSTim Vanderhoek 		f_notabs = 1;
539545f583cSTim Vanderhoek 		switch (ninitmax) {
5405dda5d0dSJosef Karthauser 		case 0:
5415dda5d0dSJosef Karthauser 			maxinode = 0;
5425dda5d0dSJosef Karthauser 		case 1:
5435dda5d0dSJosef Karthauser 			maxblock = 0;
5445dda5d0dSJosef Karthauser 		case 2:
5455dda5d0dSJosef Karthauser 			maxnlink = 0;
5465dda5d0dSJosef Karthauser 		case 3:
5475dda5d0dSJosef Karthauser 			maxuser = 0;
5485dda5d0dSJosef Karthauser 		case 4:
5495dda5d0dSJosef Karthauser 			maxgroup = 0;
5505dda5d0dSJosef Karthauser 		case 5:
5515dda5d0dSJosef Karthauser 			maxflags = 0;
5525dda5d0dSJosef Karthauser 		case 6:
5535dda5d0dSJosef Karthauser 			maxsize = 0;
5545dda5d0dSJosef Karthauser 		case 7:
5555dda5d0dSJosef Karthauser 			maxlen = 0;
5565dda5d0dSJosef Karthauser 		case 8:
5575dda5d0dSJosef Karthauser 			maxlattr = 0;
55818d8a22bSAndrey A. Chernov #ifdef COLORLS
55918d8a22bSAndrey A. Chernov 			if (!f_color)
56022ff3e9eSAndrey A. Chernov #endif
56118d8a22bSAndrey A. Chernov 				f_notabs = 0;
562545f583cSTim Vanderhoek 		}
563545f583cSTim Vanderhoek 		maxinode = makenines(maxinode);
564545f583cSTim Vanderhoek 		maxblock = makenines(maxblock);
565545f583cSTim Vanderhoek 		maxnlink = makenines(maxnlink);
566545f583cSTim Vanderhoek 		maxsize = makenines(maxsize);
567bb2b4fafSTim Vanderhoek 	} else if (initmax == NULL || *initmax == '\0')
5687304f61fSBrian Feldman 		maxlattr = maxblock = maxinode = maxlen = maxnlink =
569545f583cSTim Vanderhoek 		    maxuser = maxgroup = maxflags = maxsize = 0;
5707304f61fSBrian Feldman 	if (f_lomac)
5717304f61fSBrian Feldman 		lomac_start();
5724b88c807SRodney W. Grimes 	bcfile = 0;
5730fd510b7SJoerg Wunsch 	flags = NULL;
5744b88c807SRodney W. Grimes 	for (cur = list, entries = 0; cur; cur = cur->fts_link) {
5754b88c807SRodney W. Grimes 		if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
5764b88c807SRodney W. Grimes 			warnx("%s: %s",
5774b88c807SRodney W. Grimes 			    cur->fts_name, strerror(cur->fts_errno));
5784b88c807SRodney W. Grimes 			cur->fts_number = NO_PRINT;
579fb1000d6SAdam David 			rval = 1;
5804b88c807SRodney W. Grimes 			continue;
5814b88c807SRodney W. Grimes 		}
5824b88c807SRodney W. Grimes 		/*
5834b88c807SRodney W. Grimes 		 * P is NULL if list is the argv list, to which different rules
5844b88c807SRodney W. Grimes 		 * apply.
5854b88c807SRodney W. Grimes 		 */
5864b88c807SRodney W. Grimes 		if (p == NULL) {
5874b88c807SRodney W. Grimes 			/* Directories will be displayed later. */
5884b88c807SRodney W. Grimes 			if (cur->fts_info == FTS_D && !f_listdir) {
5894b88c807SRodney W. Grimes 				cur->fts_number = NO_PRINT;
5904b88c807SRodney W. Grimes 				continue;
5914b88c807SRodney W. Grimes 			}
5924b88c807SRodney W. Grimes 		} else {
5934b88c807SRodney W. Grimes 			/* Only display dot file if -a/-A set. */
5944b88c807SRodney W. Grimes 			if (cur->fts_name[0] == '.' && !f_listdot) {
5954b88c807SRodney W. Grimes 				cur->fts_number = NO_PRINT;
5964b88c807SRodney W. Grimes 				continue;
5974b88c807SRodney W. Grimes 			}
5984b88c807SRodney W. Grimes 		}
5994b88c807SRodney W. Grimes 		if (cur->fts_namelen > maxlen)
6004b88c807SRodney W. Grimes 			maxlen = cur->fts_namelen;
6010d86878cSDag-Erling Smørgrav 		if (f_octal || f_octal_escape) {
6026bd042dfSJosef Karthauser 			u_long t = len_octal(cur->fts_name, cur->fts_namelen);
6035dda5d0dSJosef Karthauser 
6045dda5d0dSJosef Karthauser 			if (t > maxlen)
6055dda5d0dSJosef Karthauser 				maxlen = t;
6067ea30648SDag-Erling Smørgrav 		}
6074b88c807SRodney W. Grimes 		if (needstats) {
6084b88c807SRodney W. Grimes 			sp = cur->fts_statp;
6094b88c807SRodney W. Grimes 			if (sp->st_blocks > maxblock)
6104b88c807SRodney W. Grimes 				maxblock = sp->st_blocks;
6114b88c807SRodney W. Grimes 			if (sp->st_ino > maxinode)
6124b88c807SRodney W. Grimes 				maxinode = sp->st_ino;
6134b88c807SRodney W. Grimes 			if (sp->st_nlink > maxnlink)
6144b88c807SRodney W. Grimes 				maxnlink = sp->st_nlink;
6154b88c807SRodney W. Grimes 			if (sp->st_size > maxsize)
6164b88c807SRodney W. Grimes 				maxsize = sp->st_size;
6174b88c807SRodney W. Grimes 
6184b88c807SRodney W. Grimes 			btotal += sp->st_blocks;
6194b88c807SRodney W. Grimes 			if (f_longform) {
620f3a6a64eSSheldon Hearn 				if (f_numericonly) {
621f3a6a64eSSheldon Hearn 					(void)snprintf(nuser, sizeof(nuser),
622f3a6a64eSSheldon Hearn 					    "%u", sp->st_uid);
623f3a6a64eSSheldon Hearn 					(void)snprintf(ngroup, sizeof(ngroup),
624f3a6a64eSSheldon Hearn 					    "%u", sp->st_gid);
625f3a6a64eSSheldon Hearn 					user = nuser;
626f3a6a64eSSheldon Hearn 					group = ngroup;
627f3a6a64eSSheldon Hearn 				} else {
6284b88c807SRodney W. Grimes 					user = user_from_uid(sp->st_uid, 0);
629f3a6a64eSSheldon Hearn 					group = group_from_gid(sp->st_gid, 0);
630f3a6a64eSSheldon Hearn 				}
6314b88c807SRodney W. Grimes 				if ((ulen = strlen(user)) > maxuser)
6324b88c807SRodney W. Grimes 					maxuser = ulen;
6334b88c807SRodney W. Grimes 				if ((glen = strlen(group)) > maxgroup)
6344b88c807SRodney W. Grimes 					maxgroup = glen;
6354b88c807SRodney W. Grimes 				if (f_flags) {
636141d77b8SJosef Karthauser 					flags = fflagstostr(sp->st_flags);
637141d77b8SJosef Karthauser 					if (flags != NULL && *flags == '\0') {
638141d77b8SJosef Karthauser 						free(flags);
639141d77b8SJosef Karthauser 						flags = strdup("-");
640141d77b8SJosef Karthauser 					}
641141d77b8SJosef Karthauser 					if (flags == NULL)
642141d77b8SJosef Karthauser 						err(1, NULL);
6434b88c807SRodney W. Grimes 					if ((flen = strlen(flags)) > maxflags)
6444b88c807SRodney W. Grimes 						maxflags = flen;
6454b88c807SRodney W. Grimes 				} else
6464b88c807SRodney W. Grimes 					flen = 0;
6477304f61fSBrian Feldman 				if (f_lomac) {
6487304f61fSBrian Feldman 					lattr = get_lattr(cur);
6497304f61fSBrian Feldman 					lattrlen = strlen(lattr);
6507304f61fSBrian Feldman 					if (lattrlen > maxlattr)
6517304f61fSBrian Feldman 						maxlattr = lattrlen;
6527304f61fSBrian Feldman 				} else
6537304f61fSBrian Feldman 					lattrlen = 0;
6544b88c807SRodney W. Grimes 
6557304f61fSBrian Feldman 				if ((np = malloc(sizeof(NAMES) + lattrlen +
6567304f61fSBrian Feldman 				    ulen + glen + flen + 4)) == NULL)
6574b88c807SRodney W. Grimes 					err(1, NULL);
6584b88c807SRodney W. Grimes 
6594b88c807SRodney W. Grimes 				np->user = &np->data[0];
6604b88c807SRodney W. Grimes 				(void)strcpy(np->user, user);
6614b88c807SRodney W. Grimes 				np->group = &np->data[ulen + 1];
6624b88c807SRodney W. Grimes 				(void)strcpy(np->group, group);
6634b88c807SRodney W. Grimes 
6644b88c807SRodney W. Grimes 				if (S_ISCHR(sp->st_mode) ||
6654b88c807SRodney W. Grimes 				    S_ISBLK(sp->st_mode))
6664b88c807SRodney W. Grimes 					bcfile = 1;
6674b88c807SRodney W. Grimes 
6684b88c807SRodney W. Grimes 				if (f_flags) {
6694b88c807SRodney W. Grimes 					np->flags = &np->data[ulen + glen + 2];
6704b88c807SRodney W. Grimes 					(void)strcpy(np->flags, flags);
671141d77b8SJosef Karthauser 					free(flags);
6724b88c807SRodney W. Grimes 				}
6737304f61fSBrian Feldman 				if (f_lomac) {
6747304f61fSBrian Feldman 					np->lattr = &np->data[ulen + glen + 2
6757304f61fSBrian Feldman 					    + (f_flags ? flen + 1 : 0)];
6767304f61fSBrian Feldman 					(void)strcpy(np->lattr, lattr);
6777304f61fSBrian Feldman 					free(lattr);
6787304f61fSBrian Feldman 				}
6794b88c807SRodney W. Grimes 				cur->fts_pointer = np;
6804b88c807SRodney W. Grimes 			}
6814b88c807SRodney W. Grimes 		}
6824b88c807SRodney W. Grimes 		++entries;
6834b88c807SRodney W. Grimes 	}
6844b88c807SRodney W. Grimes 
6854b88c807SRodney W. Grimes 	if (!entries)
6864b88c807SRodney W. Grimes 		return;
6874b88c807SRodney W. Grimes 
6884b88c807SRodney W. Grimes 	d.list = list;
6894b88c807SRodney W. Grimes 	d.entries = entries;
6904b88c807SRodney W. Grimes 	d.maxlen = maxlen;
6914b88c807SRodney W. Grimes 	if (needstats) {
6924b88c807SRodney W. Grimes 		d.bcfile = bcfile;
6934b88c807SRodney W. Grimes 		d.btotal = btotal;
6944b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%lu", maxblock);
6954b88c807SRodney W. Grimes 		d.s_block = strlen(buf);
6964b88c807SRodney W. Grimes 		d.s_flags = maxflags;
6977304f61fSBrian Feldman 		d.s_lattr = maxlattr;
6984b88c807SRodney W. Grimes 		d.s_group = maxgroup;
6994b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%lu", maxinode);
7004b88c807SRodney W. Grimes 		d.s_inode = strlen(buf);
7014b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%lu", maxnlink);
7024b88c807SRodney W. Grimes 		d.s_nlink = strlen(buf);
7034b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%qu", maxsize);
7044b88c807SRodney W. Grimes 		d.s_size = strlen(buf);
7054b88c807SRodney W. Grimes 		d.s_user = maxuser;
7064b88c807SRodney W. Grimes 	}
7074b88c807SRodney W. Grimes 	printfcn(&d);
7084b88c807SRodney W. Grimes 	output = 1;
7094b88c807SRodney W. Grimes 
7104b88c807SRodney W. Grimes 	if (f_longform)
7114b88c807SRodney W. Grimes 		for (cur = list; cur; cur = cur->fts_link)
7124b88c807SRodney W. Grimes 			free(cur->fts_pointer);
7137304f61fSBrian Feldman 	if (f_lomac)
7147304f61fSBrian Feldman 		lomac_stop();
7154b88c807SRodney W. Grimes }
7164b88c807SRodney W. Grimes 
7174b88c807SRodney W. Grimes /*
7184b88c807SRodney W. Grimes  * Ordering for mastercmp:
7194b88c807SRodney W. Grimes  * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories
7204b88c807SRodney W. Grimes  * as larger than directories.  Within either group, use the sort function.
7214b88c807SRodney W. Grimes  * All other levels use the sort function.  Error entries remain unsorted.
7224b88c807SRodney W. Grimes  */
7234b88c807SRodney W. Grimes static int
7244b88c807SRodney W. Grimes mastercmp(a, b)
7254b88c807SRodney W. Grimes 	const FTSENT **a, **b;
7264b88c807SRodney W. Grimes {
7274b88c807SRodney W. Grimes 	int a_info, b_info;
7284b88c807SRodney W. Grimes 
7294b88c807SRodney W. Grimes 	a_info = (*a)->fts_info;
7304b88c807SRodney W. Grimes 	if (a_info == FTS_ERR)
7314b88c807SRodney W. Grimes 		return (0);
7324b88c807SRodney W. Grimes 	b_info = (*b)->fts_info;
7334b88c807SRodney W. Grimes 	if (b_info == FTS_ERR)
7344b88c807SRodney W. Grimes 		return (0);
7354b88c807SRodney W. Grimes 
7364b88c807SRodney W. Grimes 	if (a_info == FTS_NS || b_info == FTS_NS)
7374b88c807SRodney W. Grimes 		return (namecmp(*a, *b));
7384b88c807SRodney W. Grimes 
73951f26ac5SSean Eric Fagan 	if (a_info != b_info &&
74051f26ac5SSean Eric Fagan 	    (*a)->fts_level == FTS_ROOTLEVEL && !f_listdir) {
7414b88c807SRodney W. Grimes 		if (a_info == FTS_D)
7424b88c807SRodney W. Grimes 			return (1);
74351f26ac5SSean Eric Fagan 		if (b_info == FTS_D)
7444b88c807SRodney W. Grimes 			return (-1);
74551f26ac5SSean Eric Fagan 	}
7464b88c807SRodney W. Grimes 	return (sortfcn(*a, *b));
7474b88c807SRodney W. Grimes }
748545f583cSTim Vanderhoek 
749545f583cSTim Vanderhoek /*
750545f583cSTim Vanderhoek  * Makenines() returns (10**n)-1.  This is useful for converting a width
751545f583cSTim Vanderhoek  * into a number that wide in decimal.
752545f583cSTim Vanderhoek  */
753545f583cSTim Vanderhoek static u_quad_t
754545f583cSTim Vanderhoek makenines(n)
755545f583cSTim Vanderhoek 	u_long n;
756545f583cSTim Vanderhoek {
757545f583cSTim Vanderhoek 	u_long i;
758545f583cSTim Vanderhoek 	u_quad_t reg;
759545f583cSTim Vanderhoek 
760545f583cSTim Vanderhoek 	reg = 1;
761545f583cSTim Vanderhoek 	/* Use a loop instead of pow(), since all values of n are small. */
762545f583cSTim Vanderhoek 	for (i = 0; i < n; i++)
763545f583cSTim Vanderhoek 		reg *= 10;
764545f583cSTim Vanderhoek 	reg--;
765545f583cSTim Vanderhoek 
766545f583cSTim Vanderhoek 	return reg;
767545f583cSTim Vanderhoek }
768