xref: /freebsd/bin/ls/ls.c (revision c1499cf6)
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 */
974b88c807SRodney W. Grimes int f_inode;			/* print inode */
98475727a0SPaul Traina int f_kblocks;			/* print size in kilobytes */
994b88c807SRodney W. Grimes int f_listdir;			/* list actual directory, not contents */
1004b88c807SRodney W. Grimes int f_listdot;			/* list files beginning with . */
1014b88c807SRodney W. Grimes int f_longform;			/* long listing format */
1024b88c807SRodney W. Grimes int f_nonprint;			/* show unprintables as ? */
1034b88c807SRodney W. Grimes int f_nosort;			/* don't sort output */
104008a4910SSheldon Hearn int f_notabs;			/* don't use tab-separated multi-col output */
105f3a6a64eSSheldon Hearn int f_numericonly;		/* don't convert uid/gid to name */
1067ea30648SDag-Erling Smørgrav int f_octal;			/* show unprintables as \xxx */
1070d86878cSDag-Erling Smørgrav int f_octal_escape;		/* like f_octal but use C escapes if possible */
1084b88c807SRodney W. Grimes int f_recursive;		/* ls subdirectories also */
1094b88c807SRodney W. Grimes int f_reversesort;		/* reverse whatever sort is used */
1104b88c807SRodney W. Grimes int f_sectime;			/* print the real time for all files */
1114b88c807SRodney W. Grimes int f_singlecol;		/* use single column output */
1124b88c807SRodney W. Grimes int f_size;			/* list size in short listing */
1134b88c807SRodney W. Grimes int f_statustime;		/* use time of last mode change */
1144b88c807SRodney W. Grimes int f_timesort;			/* sort by time vice name */
1154b88c807SRodney W. Grimes int f_type;			/* add type character for non-regular files */
116fb5cb208SSteve Price int f_whiteout;			/* show whiteout entries */
1177304f61fSBrian Feldman int f_lomac;			/* show LOMAC attributes */
11874985094SJosef Karthauser #ifdef COLORLS
1193885812cSJosef Karthauser int f_color;			/* add type in color for non-regular files */
1205a890e22SJosef Karthauser 
1215a890e22SJosef Karthauser char *ansi_bgcol;		/* ANSI sequence to set background colour */
1225a890e22SJosef Karthauser char *ansi_fgcol;		/* ANSI sequence to set foreground colour */
1235a890e22SJosef Karthauser char *ansi_coloff;		/* ANSI sequence to reset colours */
124c1499cf6SJosef Karthauser char *attrs_off;		/* ANSI sequence to turn off attributes */
125c1499cf6SJosef Karthauser char *enter_bold;		/* ANSI sequence to set color to bold mode */
12674985094SJosef Karthauser #endif
1274b88c807SRodney W. Grimes 
128fb1000d6SAdam David int rval;
129fb1000d6SAdam David 
1304b88c807SRodney W. Grimes int
1314b88c807SRodney W. Grimes main(argc, argv)
1324b88c807SRodney W. Grimes 	int argc;
1334b88c807SRodney W. Grimes 	char *argv[];
1344b88c807SRodney W. Grimes {
1354b88c807SRodney W. Grimes 	static char dot[] = ".", *dotav[] = { dot, NULL };
1364b88c807SRodney W. Grimes 	struct winsize win;
1374b88c807SRodney W. Grimes 	int ch, fts_options, notused;
1384b88c807SRodney W. Grimes 	char *p;
1394b88c807SRodney W. Grimes 
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);
1544b88c807SRodney W. Grimes 		}
1554b88c807SRodney W. Grimes 		else
1564b88c807SRodney W. Grimes 			termwidth = win.ws_col;
1574b88c807SRodney W. Grimes 		f_column = f_nonprint = 1;
15834994fcdSJoerg Wunsch 	} else {
1594b88c807SRodney W. Grimes 		f_singlecol = 1;
16034994fcdSJoerg Wunsch 		/* retrieve environment variable, in case of explicit -C */
1610fd510b7SJoerg Wunsch 		if ((p = getenv("COLUMNS")))
16234994fcdSJoerg Wunsch 			termwidth = atoi(p);
16334994fcdSJoerg Wunsch 	}
1644b88c807SRodney W. Grimes 
1654b88c807SRodney W. Grimes 	/* Root is -A automatically. */
1664b88c807SRodney W. Grimes 	if (!getuid())
1674b88c807SRodney W. Grimes 		f_listdot = 1;
1684b88c807SRodney W. Grimes 
1694b88c807SRodney W. Grimes 	fts_options = FTS_PHYSICAL;
1707304f61fSBrian Feldman 	while ((ch = getopt(argc, argv, "1ABCFGHLPRTWZabcdfgiklnoqrstu")) != -1) {
1714b88c807SRodney W. Grimes 		switch (ch) {
1724b88c807SRodney W. Grimes 		/*
1734b88c807SRodney W. Grimes 		 * The -1, -C and -l options all override each other so shell
1744b88c807SRodney W. Grimes 		 * aliasing works right.
1754b88c807SRodney W. Grimes 		 */
1764b88c807SRodney W. Grimes 		case '1':
1774b88c807SRodney W. Grimes 			f_singlecol = 1;
1784b88c807SRodney W. Grimes 			f_column = f_longform = 0;
1794b88c807SRodney W. Grimes 			break;
1800d86878cSDag-Erling Smørgrav 		case 'B':
1810d86878cSDag-Erling Smørgrav 			f_nonprint = 0;
1820d86878cSDag-Erling Smørgrav 			f_octal = 1;
1830d86878cSDag-Erling Smørgrav 		        f_octal_escape = 0;
1840d86878cSDag-Erling Smørgrav 			break;
1854b88c807SRodney W. Grimes 		case 'C':
1864b88c807SRodney W. Grimes 			f_column = 1;
1874b88c807SRodney W. Grimes 			f_longform = f_singlecol = 0;
1884b88c807SRodney W. Grimes 			break;
1894b88c807SRodney W. Grimes 		case 'l':
1904b88c807SRodney W. Grimes 			f_longform = 1;
1914b88c807SRodney W. Grimes 			f_column = f_singlecol = 0;
1924b88c807SRodney W. Grimes 			break;
1934b88c807SRodney W. Grimes 		/* The -c and -u options override each other. */
1944b88c807SRodney W. Grimes 		case 'c':
1954b88c807SRodney W. Grimes 			f_statustime = 1;
1964b88c807SRodney W. Grimes 			f_accesstime = 0;
1974b88c807SRodney W. Grimes 			break;
1984b88c807SRodney W. Grimes 		case 'u':
1994b88c807SRodney W. Grimes 			f_accesstime = 1;
2004b88c807SRodney W. Grimes 			f_statustime = 0;
2014b88c807SRodney W. Grimes 			break;
2024b88c807SRodney W. Grimes 		case 'F':
2034b88c807SRodney W. Grimes 			f_type = 1;
2044b88c807SRodney W. Grimes 			break;
2053a34dbf7SDag-Erling Smørgrav 		case 'H':
2063a34dbf7SDag-Erling Smørgrav 		        fts_options |= FTS_COMFOLLOW;
2073a34dbf7SDag-Erling Smørgrav 			break;
2083885812cSJosef Karthauser 		case 'G':
2093d2ddc9eSJosef Karthauser 			setenv("CLICOLOR", "", 1);
2103885812cSJosef Karthauser 			break;
2114b88c807SRodney W. Grimes 		case 'L':
2124b88c807SRodney W. Grimes 			fts_options &= ~FTS_PHYSICAL;
2134b88c807SRodney W. Grimes 			fts_options |= FTS_LOGICAL;
2144b88c807SRodney W. Grimes 			break;
2153a34dbf7SDag-Erling Smørgrav 		case 'P':
2163a34dbf7SDag-Erling Smørgrav 		        fts_options &= ~FTS_COMFOLLOW;
2173a34dbf7SDag-Erling Smørgrav 			fts_options &= ~FTS_LOGICAL;
2183a34dbf7SDag-Erling Smørgrav 			fts_options |= FTS_PHYSICAL;
2193a34dbf7SDag-Erling Smørgrav 			break;
2204b88c807SRodney W. Grimes 		case 'R':
2214b88c807SRodney W. Grimes 			f_recursive = 1;
2224b88c807SRodney W. Grimes 			break;
2234b88c807SRodney W. Grimes 		case 'a':
2244b88c807SRodney W. Grimes 			fts_options |= FTS_SEEDOT;
2254b88c807SRodney W. Grimes 			/* FALLTHROUGH */
2264b88c807SRodney W. Grimes 		case 'A':
2274b88c807SRodney W. Grimes 			f_listdot = 1;
2284b88c807SRodney W. Grimes 			break;
2294b88c807SRodney W. Grimes 		/* The -d option turns off the -R option. */
2304b88c807SRodney W. Grimes 		case 'd':
2314b88c807SRodney W. Grimes 			f_listdir = 1;
2324b88c807SRodney W. Grimes 			f_recursive = 0;
2334b88c807SRodney W. Grimes 			break;
2344b88c807SRodney W. Grimes 		case 'f':
2354b88c807SRodney W. Grimes 			f_nosort = 1;
2364b88c807SRodney W. Grimes 			break;
2374b88c807SRodney W. Grimes 		case 'g':		/* Compatibility with 4.3BSD. */
2384b88c807SRodney W. Grimes 			break;
2394b88c807SRodney W. Grimes 		case 'i':
2404b88c807SRodney W. Grimes 			f_inode = 1;
2414b88c807SRodney W. Grimes 			break;
242475727a0SPaul Traina 		case 'k':
243475727a0SPaul Traina 			f_kblocks = 1;
244475727a0SPaul Traina 			break;
245f3a6a64eSSheldon Hearn 		case 'n':
246f3a6a64eSSheldon Hearn 			f_numericonly = 1;
247f3a6a64eSSheldon Hearn 			break;
2484b88c807SRodney W. Grimes 		case 'o':
2494b88c807SRodney W. Grimes 			f_flags = 1;
2504b88c807SRodney W. Grimes 			break;
2514b88c807SRodney W. Grimes 		case 'q':
2524b88c807SRodney W. Grimes 			f_nonprint = 1;
2537ea30648SDag-Erling Smørgrav 			f_octal = 0;
2540d86878cSDag-Erling Smørgrav 		        f_octal_escape = 0;
2554b88c807SRodney W. Grimes 			break;
2564b88c807SRodney W. Grimes 		case 'r':
2574b88c807SRodney W. Grimes 			f_reversesort = 1;
2584b88c807SRodney W. Grimes 			break;
2594b88c807SRodney W. Grimes 		case 's':
2604b88c807SRodney W. Grimes 			f_size = 1;
2614b88c807SRodney W. Grimes 			break;
2624b88c807SRodney W. Grimes 		case 'T':
2634b88c807SRodney W. Grimes 			f_sectime = 1;
2644b88c807SRodney W. Grimes 			break;
2654b88c807SRodney W. Grimes 		case 't':
2664b88c807SRodney W. Grimes 			f_timesort = 1;
2674b88c807SRodney W. Grimes 			break;
268fb5cb208SSteve Price 		case 'W':
269fb5cb208SSteve Price 			f_whiteout = 1;
270fb5cb208SSteve Price 			break;
2717ea30648SDag-Erling Smørgrav 		case 'b':
2727ea30648SDag-Erling Smørgrav 			f_nonprint = 0;
2730d86878cSDag-Erling Smørgrav 		        f_octal = 0;
2740d86878cSDag-Erling Smørgrav 			f_octal_escape = 1;
2757ea30648SDag-Erling Smørgrav 			break;
2767304f61fSBrian Feldman 		case 'Z':
2777304f61fSBrian Feldman 			f_lomac = 1;
2787304f61fSBrian Feldman 			break;
2794b88c807SRodney W. Grimes 		default:
2804b88c807SRodney W. Grimes 		case '?':
2814b88c807SRodney W. Grimes 			usage();
2824b88c807SRodney W. Grimes 		}
2834b88c807SRodney W. Grimes 	}
2844b88c807SRodney W. Grimes 	argc -= optind;
2854b88c807SRodney W. Grimes 	argv += optind;
2864b88c807SRodney W. Grimes 
2873d2ddc9eSJosef Karthauser 	/* Enabling of colours is conditional on the environment. */
2883d2ddc9eSJosef Karthauser 	if (getenv("CLICOLOR") &&
2893d2ddc9eSJosef Karthauser 	    (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE")))
290d4413063SJosef Karthauser #ifdef COLORLS
2913d2ddc9eSJosef Karthauser 		if (tgetent(termcapbuf, getenv("TERM")) == 1) {
2923d2ddc9eSJosef Karthauser 			ansi_fgcol = tgetstr("AF", &bp);
2933d2ddc9eSJosef Karthauser 			ansi_bgcol = tgetstr("AB", &bp);
294c1499cf6SJosef Karthauser 			attrs_off = tgetstr("me", &bp);
295c1499cf6SJosef Karthauser 			enter_bold = tgetstr("md", &bp);
2963d2ddc9eSJosef Karthauser 
2973d2ddc9eSJosef Karthauser 			/* To switch colours off use 'op' if
2983d2ddc9eSJosef Karthauser 			 * available, otherwise use 'oc', or
2993d2ddc9eSJosef Karthauser 			 * don't do colours at all. */
3003d2ddc9eSJosef Karthauser 			ansi_coloff = tgetstr("op", &bp);
3013d2ddc9eSJosef Karthauser 			if (!ansi_coloff)
3023d2ddc9eSJosef Karthauser 				ansi_coloff = tgetstr("oc", &bp);
3033d2ddc9eSJosef Karthauser 			if (ansi_fgcol && ansi_bgcol && ansi_coloff)
3043d2ddc9eSJosef Karthauser 				f_color = 1;
3053d2ddc9eSJosef Karthauser 		}
306d4413063SJosef Karthauser #else
307d4413063SJosef Karthauser 		(void)fprintf(stderr, "Color support not compiled in.\n");
308d4413063SJosef Karthauser #endif /*COLORLS*/
3093d2ddc9eSJosef Karthauser 
310d4413063SJosef Karthauser #ifdef COLORLS
311bd82d8abSAndrey A. Chernov 	if (f_color) {
31222ff3e9eSAndrey A. Chernov 		/*
31322ff3e9eSAndrey A. Chernov 		 * We can't put tabs and color sequences together:
31422ff3e9eSAndrey A. Chernov 		 * column number will be incremented incorrectly
31522ff3e9eSAndrey A. Chernov 		 * for "stty oxtabs" mode.
31622ff3e9eSAndrey A. Chernov 		 */
31722ff3e9eSAndrey A. Chernov 		f_notabs = 1;
318bd82d8abSAndrey A. Chernov 		(void) signal(SIGINT, colorquit);
319ab08444fSMartin Cracauer 		(void) signal(SIGQUIT, colorquit);
3203885812cSJosef Karthauser 		parsecolors(getenv("LSCOLORS"));
321bd82d8abSAndrey A. Chernov 	}
32274985094SJosef Karthauser #endif
3233885812cSJosef Karthauser 
3244b88c807SRodney W. Grimes 	/*
3254b88c807SRodney W. Grimes 	 * If not -F, -i, -l, -s or -t options, don't require stat
3263885812cSJosef Karthauser 	 * information, unless in color mode in which case we do
3273885812cSJosef Karthauser 	 * need this to determine which colors to display.
3284b88c807SRodney W. Grimes 	 */
3293885812cSJosef Karthauser 	if (!f_inode && !f_longform && !f_size && !f_timesort && !f_type
33074985094SJosef Karthauser #ifdef COLORLS
33174985094SJosef Karthauser 	    && !f_color
33274985094SJosef Karthauser #endif
33374985094SJosef Karthauser 	   )
3344b88c807SRodney W. Grimes 		fts_options |= FTS_NOSTAT;
3354b88c807SRodney W. Grimes 
3364b88c807SRodney W. Grimes 	/*
3374b88c807SRodney W. Grimes 	 * If not -F, -d or -l options, follow any symbolic links listed on
3384b88c807SRodney W. Grimes 	 * the command line.
3394b88c807SRodney W. Grimes 	 */
3404b88c807SRodney W. Grimes 	if (!f_longform && !f_listdir && !f_type)
3414b88c807SRodney W. Grimes 		fts_options |= FTS_COMFOLLOW;
3424b88c807SRodney W. Grimes 
343fb5cb208SSteve Price 	/*
344fb5cb208SSteve Price 	 * If -W, show whiteout entries
345fb5cb208SSteve Price 	 */
346fb5cb208SSteve Price #ifdef FTS_WHITEOUT
347fb5cb208SSteve Price 	if (f_whiteout)
348fb5cb208SSteve Price 		fts_options |= FTS_WHITEOUT;
349fb5cb208SSteve Price #endif
350fb5cb208SSteve Price 
3514b88c807SRodney W. Grimes 	/* If -l or -s, figure out block size. */
3524b88c807SRodney W. Grimes 	if (f_longform || f_size) {
35390b0ec31SPoul-Henning Kamp 		if (f_kblocks)
35490b0ec31SPoul-Henning Kamp 			blocksize = 2;
35590b0ec31SPoul-Henning Kamp 		else {
3564b88c807SRodney W. Grimes 			(void)getbsize(&notused, &blocksize);
3574b88c807SRodney W. Grimes 			blocksize /= 512;
35890b0ec31SPoul-Henning Kamp 		}
3594b88c807SRodney W. Grimes 	}
3604b88c807SRodney W. Grimes 
3614b88c807SRodney W. Grimes 	/* Select a sort function. */
3624b88c807SRodney W. Grimes 	if (f_reversesort) {
3634b88c807SRodney W. Grimes 		if (!f_timesort)
3644b88c807SRodney W. Grimes 			sortfcn = revnamecmp;
3654b88c807SRodney W. Grimes 		else if (f_accesstime)
3664b88c807SRodney W. Grimes 			sortfcn = revacccmp;
3674b88c807SRodney W. Grimes 		else if (f_statustime)
3684b88c807SRodney W. Grimes 			sortfcn = revstatcmp;
3694b88c807SRodney W. Grimes 		else /* Use modification time. */
3704b88c807SRodney W. Grimes 			sortfcn = revmodcmp;
3714b88c807SRodney W. Grimes 	} else {
3724b88c807SRodney W. Grimes 		if (!f_timesort)
3734b88c807SRodney W. Grimes 			sortfcn = namecmp;
3744b88c807SRodney W. Grimes 		else if (f_accesstime)
3754b88c807SRodney W. Grimes 			sortfcn = acccmp;
3764b88c807SRodney W. Grimes 		else if (f_statustime)
3774b88c807SRodney W. Grimes 			sortfcn = statcmp;
3784b88c807SRodney W. Grimes 		else /* Use modification time. */
3794b88c807SRodney W. Grimes 			sortfcn = modcmp;
3804b88c807SRodney W. Grimes 	}
3814b88c807SRodney W. Grimes 
3824b88c807SRodney W. Grimes 	/* Select a print function. */
3834b88c807SRodney W. Grimes 	if (f_singlecol)
3844b88c807SRodney W. Grimes 		printfcn = printscol;
3854b88c807SRodney W. Grimes 	else if (f_longform)
3864b88c807SRodney W. Grimes 		printfcn = printlong;
3874b88c807SRodney W. Grimes 	else
3884b88c807SRodney W. Grimes 		printfcn = printcol;
3894b88c807SRodney W. Grimes 
3904b88c807SRodney W. Grimes 	if (argc)
3914b88c807SRodney W. Grimes 		traverse(argc, argv, fts_options);
3924b88c807SRodney W. Grimes 	else
3934b88c807SRodney W. Grimes 		traverse(1, dotav, fts_options);
394fb1000d6SAdam David 	exit(rval);
3954b88c807SRodney W. Grimes }
3964b88c807SRodney W. Grimes 
3974b88c807SRodney W. Grimes static int output;			/* If anything output. */
3984b88c807SRodney W. Grimes 
3994b88c807SRodney W. Grimes /*
4004b88c807SRodney W. Grimes  * Traverse() walks the logical directory structure specified by the argv list
4014b88c807SRodney W. Grimes  * in the order specified by the mastercmp() comparison function.  During the
4024b88c807SRodney W. Grimes  * traversal it passes linked lists of structures to display() which represent
4034b88c807SRodney W. Grimes  * a superset (may be exact set) of the files to be displayed.
4044b88c807SRodney W. Grimes  */
4054b88c807SRodney W. Grimes static void
4064b88c807SRodney W. Grimes traverse(argc, argv, options)
4074b88c807SRodney W. Grimes 	int argc, options;
4084b88c807SRodney W. Grimes 	char *argv[];
4094b88c807SRodney W. Grimes {
4104b88c807SRodney W. Grimes 	FTS *ftsp;
4114b88c807SRodney W. Grimes 	FTSENT *p, *chp;
4124b88c807SRodney W. Grimes 	int ch_options;
4134b88c807SRodney W. Grimes 
4144b88c807SRodney W. Grimes 	if ((ftsp =
4154b88c807SRodney W. Grimes 	    fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
4164b88c807SRodney W. Grimes 		err(1, NULL);
4174b88c807SRodney W. Grimes 
4184b88c807SRodney W. Grimes 	display(NULL, fts_children(ftsp, 0));
4194b88c807SRodney W. Grimes 	if (f_listdir)
4204b88c807SRodney W. Grimes 		return;
4214b88c807SRodney W. Grimes 
4224b88c807SRodney W. Grimes 	/*
4234b88c807SRodney W. Grimes 	 * If not recursing down this tree and don't need stat info, just get
4244b88c807SRodney W. Grimes 	 * the names.
4254b88c807SRodney W. Grimes 	 */
4264b88c807SRodney W. Grimes 	ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;
4274b88c807SRodney W. Grimes 
4284b88c807SRodney W. Grimes 	while ((p = fts_read(ftsp)) != NULL)
4294b88c807SRodney W. Grimes 		switch (p->fts_info) {
4304b88c807SRodney W. Grimes 		case FTS_DC:
4314b88c807SRodney W. Grimes 			warnx("%s: directory causes a cycle", p->fts_name);
4324b88c807SRodney W. Grimes 			break;
4334b88c807SRodney W. Grimes 		case FTS_DNR:
4344b88c807SRodney W. Grimes 		case FTS_ERR:
4354b88c807SRodney W. Grimes 			warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
436fb1000d6SAdam David 			rval = 1;
4374b88c807SRodney W. Grimes 			break;
4384b88c807SRodney W. Grimes 		case FTS_D:
4394b88c807SRodney W. Grimes 			if (p->fts_level != FTS_ROOTLEVEL &&
4404b88c807SRodney W. Grimes 			    p->fts_name[0] == '.' && !f_listdot)
4414b88c807SRodney W. Grimes 				break;
4424b88c807SRodney W. Grimes 
4434b88c807SRodney W. Grimes 			/*
4444b88c807SRodney W. Grimes 			 * If already output something, put out a newline as
4454b88c807SRodney W. Grimes 			 * a separator.  If multiple arguments, precede each
4464b88c807SRodney W. Grimes 			 * directory with its name.
4474b88c807SRodney W. Grimes 			 */
4484b88c807SRodney W. Grimes 			if (output)
4494b88c807SRodney W. Grimes 				(void)printf("\n%s:\n", p->fts_path);
4504b88c807SRodney W. Grimes 			else if (argc > 1) {
4514b88c807SRodney W. Grimes 				(void)printf("%s:\n", p->fts_path);
4524b88c807SRodney W. Grimes 				output = 1;
4534b88c807SRodney W. Grimes 			}
4544b88c807SRodney W. Grimes 
4554b88c807SRodney W. Grimes 			chp = fts_children(ftsp, ch_options);
4564b88c807SRodney W. Grimes 			display(p, chp);
4574b88c807SRodney W. Grimes 
4584b88c807SRodney W. Grimes 			if (!f_recursive && chp != NULL)
4594b88c807SRodney W. Grimes 				(void)fts_set(ftsp, p, FTS_SKIP);
4604b88c807SRodney W. Grimes 			break;
4614b88c807SRodney W. Grimes 		}
4624b88c807SRodney W. Grimes 	if (errno)
4634b88c807SRodney W. Grimes 		err(1, "fts_read");
4644b88c807SRodney W. Grimes }
4654b88c807SRodney W. Grimes 
4664b88c807SRodney W. Grimes /*
4674b88c807SRodney W. Grimes  * Display() takes a linked list of FTSENT structures and passes the list
4684b88c807SRodney W. Grimes  * along with any other necessary information to the print function.  P
4694b88c807SRodney W. Grimes  * points to the parent directory of the display list.
4704b88c807SRodney W. Grimes  */
4714b88c807SRodney W. Grimes static void
4724b88c807SRodney W. Grimes display(p, list)
4734b88c807SRodney W. Grimes 	FTSENT *p, *list;
4744b88c807SRodney W. Grimes {
4754b88c807SRodney W. Grimes 	struct stat *sp;
4764b88c807SRodney W. Grimes 	DISPLAY d;
4774b88c807SRodney W. Grimes 	FTSENT *cur;
4784b88c807SRodney W. Grimes 	NAMES *np;
4794b88c807SRodney W. Grimes 	u_quad_t maxsize;
4807304f61fSBrian Feldman 	u_long btotal, maxblock, maxinode, maxlen, maxnlink, maxlattr;
4817304f61fSBrian Feldman 	int bcfile, flen, glen, ulen, lattrlen, maxflags, maxgroup, maxuser;
482545f583cSTim Vanderhoek 	char *initmax;
4834b88c807SRodney W. Grimes 	int entries, needstats;
4847304f61fSBrian Feldman 	char *user, *group, *flags, *lattr;
485008a4910SSheldon Hearn 	char buf[STRBUF_SIZEOF(u_quad_t) + 1];
486008a4910SSheldon Hearn 	char ngroup[STRBUF_SIZEOF(uid_t) + 1];
487008a4910SSheldon Hearn 	char nuser[STRBUF_SIZEOF(gid_t) + 1];
4884b88c807SRodney W. Grimes 
4894b88c807SRodney W. Grimes 	/*
4904b88c807SRodney W. Grimes 	 * If list is NULL there are two possibilities: that the parent
4914b88c807SRodney W. Grimes 	 * directory p has no children, or that fts_children() returned an
4924b88c807SRodney W. Grimes 	 * error.  We ignore the error case since it will be replicated
4934b88c807SRodney W. Grimes 	 * on the next call to fts_read() on the post-order visit to the
49446be34b9SKris Kennaway 	 * directory p, and will be signaled in traverse().
4954b88c807SRodney W. Grimes 	 */
4964b88c807SRodney W. Grimes 	if (list == NULL)
4974b88c807SRodney W. Grimes 		return;
4984b88c807SRodney W. Grimes 
4994b88c807SRodney W. Grimes 	needstats = f_inode || f_longform || f_size;
5004b88c807SRodney W. Grimes 	flen = 0;
501545f583cSTim Vanderhoek 	btotal = 0;
502545f583cSTim Vanderhoek 	initmax = getenv("LS_COLWIDTHS");
503545f583cSTim Vanderhoek 	/* Fields match -lios order.  New ones should be added at the end. */
504545f583cSTim Vanderhoek 	if (initmax != NULL && *initmax != '\0') {
505545f583cSTim Vanderhoek 		char *initmax2, *jinitmax;
506545f583cSTim Vanderhoek 		int ninitmax;
507545f583cSTim Vanderhoek 
508545f583cSTim Vanderhoek 		/* Fill-in "::" as "0:0:0" for the sake of scanf. */
509545f583cSTim Vanderhoek 		jinitmax = initmax2 = malloc(strlen(initmax) * 2 + 2);
510545f583cSTim Vanderhoek 		if (jinitmax == NULL)
511545f583cSTim Vanderhoek 			err(1, NULL);
512545f583cSTim Vanderhoek 		if (*initmax == ':')
513545f583cSTim Vanderhoek 			strcpy(initmax2, "0:"), initmax2 += 2;
514545f583cSTim Vanderhoek 		else
515545f583cSTim Vanderhoek 			*initmax2++ = *initmax, *initmax2 = '\0';
516545f583cSTim Vanderhoek 		for (initmax++; *initmax != '\0'; initmax++) {
517545f583cSTim Vanderhoek 			if (initmax[-1] == ':' && initmax[0] == ':') {
518545f583cSTim Vanderhoek 				*initmax2++ = '0';
519545f583cSTim Vanderhoek 				*initmax2++ = initmax[0];
520545f583cSTim Vanderhoek 				initmax2[1] = '\0';
521545f583cSTim Vanderhoek 			} else {
522545f583cSTim Vanderhoek 				*initmax2++ = initmax[0];
523545f583cSTim Vanderhoek 				initmax2[1] = '\0';
524545f583cSTim Vanderhoek 			}
525545f583cSTim Vanderhoek 		}
526545f583cSTim Vanderhoek 		if (initmax2[-1] == ':') strcpy(initmax2, "0");
527545f583cSTim Vanderhoek 
528545f583cSTim Vanderhoek 		ninitmax = sscanf(jinitmax,
5297304f61fSBrian Feldman 		    " %lu : %lu : %lu : %i : %i : %i : %qu : %lu : %lu ",
530545f583cSTim Vanderhoek 		    &maxinode, &maxblock, &maxnlink, &maxuser,
5317304f61fSBrian Feldman 		    &maxgroup, &maxflags, &maxsize, &maxlen, &maxlattr);
532545f583cSTim Vanderhoek 		f_notabs = 1;
533545f583cSTim Vanderhoek 		switch (ninitmax) {
534545f583cSTim Vanderhoek 		 case 0: maxinode = 0;
535545f583cSTim Vanderhoek 		 case 1: maxblock = 0;
536545f583cSTim Vanderhoek 		 case 2: maxnlink = 0;
537545f583cSTim Vanderhoek 		 case 3: maxuser  = 0;
538545f583cSTim Vanderhoek 		 case 4: maxgroup = 0;
539545f583cSTim Vanderhoek 		 case 5: maxflags = 0;
540545f583cSTim Vanderhoek 		 case 6: maxsize  = 0;
54122ff3e9eSAndrey A. Chernov 		 case 7: maxlen   = 0;
5427304f61fSBrian Feldman 		 case 8: maxlattr = 0;
54318d8a22bSAndrey A. Chernov #ifdef COLORLS
54418d8a22bSAndrey A. Chernov 		 if (!f_color)
54522ff3e9eSAndrey A. Chernov #endif
54618d8a22bSAndrey A. Chernov 			 f_notabs = 0;
547545f583cSTim Vanderhoek 		}
548545f583cSTim Vanderhoek 		maxinode = makenines(maxinode);
549545f583cSTim Vanderhoek 		maxblock = makenines(maxblock);
550545f583cSTim Vanderhoek 		maxnlink = makenines(maxnlink);
551545f583cSTim Vanderhoek 		maxsize = makenines(maxsize);
552bb2b4fafSTim Vanderhoek 	} else if (initmax == NULL || *initmax == '\0')
5537304f61fSBrian Feldman 		maxlattr = maxblock = maxinode = maxlen = maxnlink =
554545f583cSTim Vanderhoek 		    maxuser = maxgroup = maxflags = maxsize = 0;
5557304f61fSBrian Feldman 	if (f_lomac)
5567304f61fSBrian Feldman 		lomac_start();
5574b88c807SRodney W. Grimes 	bcfile = 0;
5580fd510b7SJoerg Wunsch 	flags = NULL;
5594b88c807SRodney W. Grimes 	for (cur = list, entries = 0; cur; cur = cur->fts_link) {
5604b88c807SRodney W. Grimes 		if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
5614b88c807SRodney W. Grimes 			warnx("%s: %s",
5624b88c807SRodney W. Grimes 			    cur->fts_name, strerror(cur->fts_errno));
5634b88c807SRodney W. Grimes 			cur->fts_number = NO_PRINT;
564fb1000d6SAdam David 			rval = 1;
5654b88c807SRodney W. Grimes 			continue;
5664b88c807SRodney W. Grimes 		}
5674b88c807SRodney W. Grimes 
5684b88c807SRodney W. Grimes 		/*
5694b88c807SRodney W. Grimes 		 * P is NULL if list is the argv list, to which different rules
5704b88c807SRodney W. Grimes 		 * apply.
5714b88c807SRodney W. Grimes 		 */
5724b88c807SRodney W. Grimes 		if (p == NULL) {
5734b88c807SRodney W. Grimes 			/* Directories will be displayed later. */
5744b88c807SRodney W. Grimes 			if (cur->fts_info == FTS_D && !f_listdir) {
5754b88c807SRodney W. Grimes 				cur->fts_number = NO_PRINT;
5764b88c807SRodney W. Grimes 				continue;
5774b88c807SRodney W. Grimes 			}
5784b88c807SRodney W. Grimes 		} else {
5794b88c807SRodney W. Grimes 			/* Only display dot file if -a/-A set. */
5804b88c807SRodney W. Grimes 			if (cur->fts_name[0] == '.' && !f_listdot) {
5814b88c807SRodney W. Grimes 				cur->fts_number = NO_PRINT;
5824b88c807SRodney W. Grimes 				continue;
5834b88c807SRodney W. Grimes 			}
5844b88c807SRodney W. Grimes 		}
5854b88c807SRodney W. Grimes 		if (cur->fts_namelen > maxlen)
5864b88c807SRodney W. Grimes 			maxlen = cur->fts_namelen;
5870d86878cSDag-Erling Smørgrav 		if (f_octal || f_octal_escape) {
5887ea30648SDag-Erling Smørgrav 		        int t = len_octal(cur->fts_name, cur->fts_namelen);
5897ea30648SDag-Erling Smørgrav 			if (t > maxlen) maxlen = t;
5907ea30648SDag-Erling Smørgrav 		}
5914b88c807SRodney W. Grimes 		if (needstats) {
5924b88c807SRodney W. Grimes 			sp = cur->fts_statp;
5934b88c807SRodney W. Grimes 			if (sp->st_blocks > maxblock)
5944b88c807SRodney W. Grimes 				maxblock = sp->st_blocks;
5954b88c807SRodney W. Grimes 			if (sp->st_ino > maxinode)
5964b88c807SRodney W. Grimes 				maxinode = sp->st_ino;
5974b88c807SRodney W. Grimes 			if (sp->st_nlink > maxnlink)
5984b88c807SRodney W. Grimes 				maxnlink = sp->st_nlink;
5994b88c807SRodney W. Grimes 			if (sp->st_size > maxsize)
6004b88c807SRodney W. Grimes 				maxsize = sp->st_size;
6014b88c807SRodney W. Grimes 
6024b88c807SRodney W. Grimes 			btotal += sp->st_blocks;
6034b88c807SRodney W. Grimes 			if (f_longform) {
604f3a6a64eSSheldon Hearn 				if (f_numericonly) {
605f3a6a64eSSheldon Hearn 					(void)snprintf(nuser, sizeof(nuser),
606f3a6a64eSSheldon Hearn 					    "%u", sp->st_uid);
607f3a6a64eSSheldon Hearn 					(void)snprintf(ngroup, sizeof(ngroup),
608f3a6a64eSSheldon Hearn 					    "%u", sp->st_gid);
609f3a6a64eSSheldon Hearn 					user = nuser;
610f3a6a64eSSheldon Hearn 					group = ngroup;
611f3a6a64eSSheldon Hearn 				} else {
6124b88c807SRodney W. Grimes 					user = user_from_uid(sp->st_uid, 0);
613f3a6a64eSSheldon Hearn 					group = group_from_gid(sp->st_gid, 0);
614f3a6a64eSSheldon Hearn 				}
6154b88c807SRodney W. Grimes 				if ((ulen = strlen(user)) > maxuser)
6164b88c807SRodney W. Grimes 					maxuser = ulen;
6174b88c807SRodney W. Grimes 				if ((glen = strlen(group)) > maxgroup)
6184b88c807SRodney W. Grimes 					maxgroup = glen;
6194b88c807SRodney W. Grimes 				if (f_flags) {
620141d77b8SJosef Karthauser 					flags = fflagstostr(sp->st_flags);
621141d77b8SJosef Karthauser 					if (flags != NULL && *flags == '\0') {
622141d77b8SJosef Karthauser 						free(flags);
623141d77b8SJosef Karthauser 						flags = strdup("-");
624141d77b8SJosef Karthauser 					}
625141d77b8SJosef Karthauser 					if (flags == NULL)
626141d77b8SJosef Karthauser 						err(1, NULL);
6274b88c807SRodney W. Grimes 					if ((flen = strlen(flags)) > maxflags)
6284b88c807SRodney W. Grimes 						maxflags = flen;
6294b88c807SRodney W. Grimes 				} else
6304b88c807SRodney W. Grimes 					flen = 0;
6317304f61fSBrian Feldman 				if (f_lomac) {
6327304f61fSBrian Feldman 					lattr = get_lattr(cur);
6337304f61fSBrian Feldman 					lattrlen = strlen(lattr);
6347304f61fSBrian Feldman 					if (lattrlen > maxlattr)
6357304f61fSBrian Feldman 						maxlattr = lattrlen;
6367304f61fSBrian Feldman 				} else
6377304f61fSBrian Feldman 					lattrlen = 0;
6384b88c807SRodney W. Grimes 
6397304f61fSBrian Feldman 				if ((np = malloc(sizeof(NAMES) + lattrlen +
6407304f61fSBrian Feldman 				    ulen + glen + flen + 4)) == NULL)
6414b88c807SRodney W. Grimes 					err(1, NULL);
6424b88c807SRodney W. Grimes 
6434b88c807SRodney W. Grimes 				np->user = &np->data[0];
6444b88c807SRodney W. Grimes 				(void)strcpy(np->user, user);
6454b88c807SRodney W. Grimes 				np->group = &np->data[ulen + 1];
6464b88c807SRodney W. Grimes 				(void)strcpy(np->group, group);
6474b88c807SRodney W. Grimes 
6484b88c807SRodney W. Grimes 				if (S_ISCHR(sp->st_mode) ||
6494b88c807SRodney W. Grimes 				    S_ISBLK(sp->st_mode))
6504b88c807SRodney W. Grimes 					bcfile = 1;
6514b88c807SRodney W. Grimes 
6524b88c807SRodney W. Grimes 				if (f_flags) {
6534b88c807SRodney W. Grimes 					np->flags = &np->data[ulen + glen + 2];
6544b88c807SRodney W. Grimes 				  	(void)strcpy(np->flags, flags);
655141d77b8SJosef Karthauser 					free(flags);
6564b88c807SRodney W. Grimes 				}
6577304f61fSBrian Feldman 				if (f_lomac) {
6587304f61fSBrian Feldman 					np->lattr = &np->data[ulen + glen + 2
6597304f61fSBrian Feldman 					    + (f_flags ? flen + 1 : 0)];
6607304f61fSBrian Feldman 					(void)strcpy(np->lattr, lattr);
6617304f61fSBrian Feldman 					free(lattr);
6627304f61fSBrian Feldman 				}
6634b88c807SRodney W. Grimes 				cur->fts_pointer = np;
6644b88c807SRodney W. Grimes 			}
6654b88c807SRodney W. Grimes 		}
6664b88c807SRodney W. Grimes 		++entries;
6674b88c807SRodney W. Grimes 	}
6684b88c807SRodney W. Grimes 
6694b88c807SRodney W. Grimes 	if (!entries)
6704b88c807SRodney W. Grimes 		return;
6714b88c807SRodney W. Grimes 
6724b88c807SRodney W. Grimes 	d.list = list;
6734b88c807SRodney W. Grimes 	d.entries = entries;
6744b88c807SRodney W. Grimes 	d.maxlen = maxlen;
6754b88c807SRodney W. Grimes 	if (needstats) {
6764b88c807SRodney W. Grimes 		d.bcfile = bcfile;
6774b88c807SRodney W. Grimes 		d.btotal = btotal;
6784b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%lu", maxblock);
6794b88c807SRodney W. Grimes 		d.s_block = strlen(buf);
6804b88c807SRodney W. Grimes 		d.s_flags = maxflags;
6817304f61fSBrian Feldman 		d.s_lattr = maxlattr;
6824b88c807SRodney W. Grimes 		d.s_group = maxgroup;
6834b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%lu", maxinode);
6844b88c807SRodney W. Grimes 		d.s_inode = strlen(buf);
6854b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%lu", maxnlink);
6864b88c807SRodney W. Grimes 		d.s_nlink = strlen(buf);
6874b88c807SRodney W. Grimes 		(void)snprintf(buf, sizeof(buf), "%qu", maxsize);
6884b88c807SRodney W. Grimes 		d.s_size = strlen(buf);
6894b88c807SRodney W. Grimes 		d.s_user = maxuser;
6904b88c807SRodney W. Grimes 	}
6914b88c807SRodney W. Grimes 
6924b88c807SRodney W. Grimes 	printfcn(&d);
6934b88c807SRodney W. Grimes 	output = 1;
6944b88c807SRodney W. Grimes 
6954b88c807SRodney W. Grimes 	if (f_longform)
6964b88c807SRodney W. Grimes 		for (cur = list; cur; cur = cur->fts_link)
6974b88c807SRodney W. Grimes 			free(cur->fts_pointer);
6987304f61fSBrian Feldman 	if (f_lomac)
6997304f61fSBrian Feldman 		lomac_stop();
7004b88c807SRodney W. Grimes }
7014b88c807SRodney W. Grimes 
7024b88c807SRodney W. Grimes /*
7034b88c807SRodney W. Grimes  * Ordering for mastercmp:
7044b88c807SRodney W. Grimes  * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories
7054b88c807SRodney W. Grimes  * as larger than directories.  Within either group, use the sort function.
7064b88c807SRodney W. Grimes  * All other levels use the sort function.  Error entries remain unsorted.
7074b88c807SRodney W. Grimes  */
7084b88c807SRodney W. Grimes static int
7094b88c807SRodney W. Grimes mastercmp(a, b)
7104b88c807SRodney W. Grimes 	const FTSENT **a, **b;
7114b88c807SRodney W. Grimes {
7124b88c807SRodney W. Grimes 	int a_info, b_info;
7134b88c807SRodney W. Grimes 
7144b88c807SRodney W. Grimes 	a_info = (*a)->fts_info;
7154b88c807SRodney W. Grimes 	if (a_info == FTS_ERR)
7164b88c807SRodney W. Grimes 		return (0);
7174b88c807SRodney W. Grimes 	b_info = (*b)->fts_info;
7184b88c807SRodney W. Grimes 	if (b_info == FTS_ERR)
7194b88c807SRodney W. Grimes 		return (0);
7204b88c807SRodney W. Grimes 
7214b88c807SRodney W. Grimes 	if (a_info == FTS_NS || b_info == FTS_NS)
7224b88c807SRodney W. Grimes 		return (namecmp(*a, *b));
7234b88c807SRodney W. Grimes 
72451f26ac5SSean Eric Fagan 	if (a_info != b_info &&
72551f26ac5SSean Eric Fagan 	    (*a)->fts_level == FTS_ROOTLEVEL && !f_listdir) {
7264b88c807SRodney W. Grimes 		if (a_info == FTS_D)
7274b88c807SRodney W. Grimes 			return (1);
72851f26ac5SSean Eric Fagan 		if (b_info == FTS_D)
7294b88c807SRodney W. Grimes 			return (-1);
73051f26ac5SSean Eric Fagan 	}
7314b88c807SRodney W. Grimes 	return (sortfcn(*a, *b));
7324b88c807SRodney W. Grimes }
733545f583cSTim Vanderhoek 
734545f583cSTim Vanderhoek /*
735545f583cSTim Vanderhoek  * Makenines() returns (10**n)-1.  This is useful for converting a width
736545f583cSTim Vanderhoek  * into a number that wide in decimal.
737545f583cSTim Vanderhoek  */
738545f583cSTim Vanderhoek static u_quad_t
739545f583cSTim Vanderhoek makenines(n)
740545f583cSTim Vanderhoek 	u_long n;
741545f583cSTim Vanderhoek {
742545f583cSTim Vanderhoek 	u_long i;
743545f583cSTim Vanderhoek 	u_quad_t reg;
744545f583cSTim Vanderhoek 
745545f583cSTim Vanderhoek 	reg = 1;
746545f583cSTim Vanderhoek 	/* Use a loop instead of pow(), since all values of n are small. */
747545f583cSTim Vanderhoek 	for (i = 0; i < n; i++)
748545f583cSTim Vanderhoek 		reg *= 10;
749545f583cSTim Vanderhoek 	reg--;
750545f583cSTim Vanderhoek 
751545f583cSTim Vanderhoek 	return reg;
752545f583cSTim Vanderhoek }
753