xref: /freebsd/bin/ls/print.c (revision fb5cb2083a29d51413797623c54dea0c5a40243c)
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.
3589730b29SDavid Greenman  *
36fb5cb208SSteve Price  *	$Id: print.c,v 1.8 1996/01/20 10:31:14 mpp Exp $
374b88c807SRodney W. Grimes  */
384b88c807SRodney W. Grimes 
394b88c807SRodney W. Grimes #ifndef lint
40fb5cb208SSteve Price static char const sccsid[] = "@(#)print.c	8.4 (Berkeley) 4/17/94";
414b88c807SRodney W. Grimes #endif /* not lint */
424b88c807SRodney W. Grimes 
434b88c807SRodney W. Grimes #include <sys/param.h>
444b88c807SRodney W. Grimes #include <sys/stat.h>
454b88c807SRodney W. Grimes 
464b88c807SRodney W. Grimes #include <err.h>
474b88c807SRodney W. Grimes #include <errno.h>
484b88c807SRodney W. Grimes #include <fts.h>
494b88c807SRodney W. Grimes #include <grp.h>
504b88c807SRodney W. Grimes #include <pwd.h>
514b88c807SRodney W. Grimes #include <stdio.h>
524b88c807SRodney W. Grimes #include <stdlib.h>
534b88c807SRodney W. Grimes #include <string.h>
544b88c807SRodney W. Grimes #include <time.h>
554b88c807SRodney W. Grimes #include <unistd.h>
564b88c807SRodney W. Grimes 
574b88c807SRodney W. Grimes #include "ls.h"
584b88c807SRodney W. Grimes #include "extern.h"
594b88c807SRodney W. Grimes 
604b88c807SRodney W. Grimes static int	printaname __P((FTSENT *, u_long, u_long));
614b88c807SRodney W. Grimes static void	printlink __P((FTSENT *));
624b88c807SRodney W. Grimes static void	printtime __P((time_t));
634b88c807SRodney W. Grimes static int	printtype __P((u_int));
644b88c807SRodney W. Grimes 
654b88c807SRodney W. Grimes #define	IS_NOPRINT(p)	((p)->fts_number == NO_PRINT)
664b88c807SRodney W. Grimes 
674b88c807SRodney W. Grimes void
684b88c807SRodney W. Grimes printscol(dp)
694b88c807SRodney W. Grimes 	DISPLAY *dp;
704b88c807SRodney W. Grimes {
714b88c807SRodney W. Grimes 	FTSENT *p;
724b88c807SRodney W. Grimes 
734b88c807SRodney W. Grimes 	for (p = dp->list; p; p = p->fts_link) {
744b88c807SRodney W. Grimes 		if (IS_NOPRINT(p))
754b88c807SRodney W. Grimes 			continue;
764b88c807SRodney W. Grimes 		(void)printaname(p, dp->s_inode, dp->s_block);
774b88c807SRodney W. Grimes 		(void)putchar('\n');
784b88c807SRodney W. Grimes 	}
794b88c807SRodney W. Grimes }
804b88c807SRodney W. Grimes 
814b88c807SRodney W. Grimes void
824b88c807SRodney W. Grimes printlong(dp)
834b88c807SRodney W. Grimes 	DISPLAY *dp;
844b88c807SRodney W. Grimes {
854b88c807SRodney W. Grimes 	struct stat *sp;
864b88c807SRodney W. Grimes 	FTSENT *p;
874b88c807SRodney W. Grimes 	NAMES *np;
884b88c807SRodney W. Grimes 	char buf[20];
894b88c807SRodney W. Grimes 
904b88c807SRodney W. Grimes 	if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
914b88c807SRodney W. Grimes 		(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
924b88c807SRodney W. Grimes 
934b88c807SRodney W. Grimes 	for (p = dp->list; p; p = p->fts_link) {
944b88c807SRodney W. Grimes 		if (IS_NOPRINT(p))
954b88c807SRodney W. Grimes 			continue;
964b88c807SRodney W. Grimes 		sp = p->fts_statp;
974b88c807SRodney W. Grimes 		if (f_inode)
98fb5cb208SSteve Price 			(void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino);
994b88c807SRodney W. Grimes 		if (f_size)
1004b88c807SRodney W. Grimes 			(void)printf("%*qd ",
1014b88c807SRodney W. Grimes 			    dp->s_block, howmany(sp->st_blocks, blocksize));
1024b88c807SRodney W. Grimes 		(void)strmode(sp->st_mode, buf);
1034b88c807SRodney W. Grimes 		np = p->fts_pointer;
1044b88c807SRodney W. Grimes 		(void)printf("%s %*u %-*s  %-*s  ", buf, dp->s_nlink,
1054b88c807SRodney W. Grimes 		    sp->st_nlink, dp->s_user, np->user, dp->s_group,
1064b88c807SRodney W. Grimes 		    np->group);
1074b88c807SRodney W. Grimes 		if (f_flags)
1084b88c807SRodney W. Grimes 			(void)printf("%-*s ", dp->s_flags, np->flags);
1094b88c807SRodney W. Grimes 		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
110df2fbf15SJoerg Wunsch 			if (minor(sp->st_rdev) > 255)
111df2fbf15SJoerg Wunsch 				(void)printf("%3d, 0x%08x ",
112df2fbf15SJoerg Wunsch 				    major(sp->st_rdev), minor(sp->st_rdev));
113df2fbf15SJoerg Wunsch 			else
1144b88c807SRodney W. Grimes 				(void)printf("%3d, %3d ",
1154b88c807SRodney W. Grimes 				    major(sp->st_rdev), minor(sp->st_rdev));
1164b88c807SRodney W. Grimes 		else if (dp->bcfile)
1174b88c807SRodney W. Grimes 			(void)printf("%*s%*qd ",
1184b88c807SRodney W. Grimes 			    8 - dp->s_size, "", dp->s_size, sp->st_size);
1194b88c807SRodney W. Grimes 		else
1204b88c807SRodney W. Grimes 			(void)printf("%*qd ", dp->s_size, sp->st_size);
1214b88c807SRodney W. Grimes 		if (f_accesstime)
1224b88c807SRodney W. Grimes 			printtime(sp->st_atime);
1234b88c807SRodney W. Grimes 		else if (f_statustime)
1244b88c807SRodney W. Grimes 			printtime(sp->st_ctime);
1254b88c807SRodney W. Grimes 		else
1264b88c807SRodney W. Grimes 			printtime(sp->st_mtime);
1274b88c807SRodney W. Grimes 		(void)printf("%s", p->fts_name);
1284b88c807SRodney W. Grimes 		if (f_type)
1294b88c807SRodney W. Grimes 			(void)printtype(sp->st_mode);
1304b88c807SRodney W. Grimes 		if (S_ISLNK(sp->st_mode))
1314b88c807SRodney W. Grimes 			printlink(p);
1324b88c807SRodney W. Grimes 		(void)putchar('\n');
1334b88c807SRodney W. Grimes 	}
1344b88c807SRodney W. Grimes }
1354b88c807SRodney W. Grimes 
1364b88c807SRodney W. Grimes #define	TAB	8
1374b88c807SRodney W. Grimes 
1384b88c807SRodney W. Grimes void
1394b88c807SRodney W. Grimes printcol(dp)
1404b88c807SRodney W. Grimes 	DISPLAY *dp;
1414b88c807SRodney W. Grimes {
1424b88c807SRodney W. Grimes 	extern int termwidth;
1434b88c807SRodney W. Grimes 	static FTSENT **array;
1444b88c807SRodney W. Grimes 	static int lastentries = -1;
1454b88c807SRodney W. Grimes 	FTSENT *p;
1464b88c807SRodney W. Grimes 	int base, chcnt, cnt, col, colwidth, num;
1474b88c807SRodney W. Grimes 	int endcol, numcols, numrows, row;
1484b88c807SRodney W. Grimes 
1494b88c807SRodney W. Grimes 	/*
1504b88c807SRodney W. Grimes 	 * Have to do random access in the linked list -- build a table
1514b88c807SRodney W. Grimes 	 * of pointers.
1524b88c807SRodney W. Grimes 	 */
1534b88c807SRodney W. Grimes 	if (dp->entries > lastentries) {
1544b88c807SRodney W. Grimes 		lastentries = dp->entries;
1554b88c807SRodney W. Grimes 		if ((array =
1564b88c807SRodney W. Grimes 		    realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
1574b88c807SRodney W. Grimes 			warn(NULL);
1584b88c807SRodney W. Grimes 			printscol(dp);
1594b88c807SRodney W. Grimes 		}
1604b88c807SRodney W. Grimes 	}
1614b88c807SRodney W. Grimes 	for (p = dp->list, num = 0; p; p = p->fts_link)
1624b88c807SRodney W. Grimes 		if (p->fts_number != NO_PRINT)
1634b88c807SRodney W. Grimes 			array[num++] = p;
1644b88c807SRodney W. Grimes 
1654b88c807SRodney W. Grimes 	colwidth = dp->maxlen;
1664b88c807SRodney W. Grimes 	if (f_inode)
1674b88c807SRodney W. Grimes 		colwidth += dp->s_inode + 1;
1684b88c807SRodney W. Grimes 	if (f_size)
1694b88c807SRodney W. Grimes 		colwidth += dp->s_block + 1;
1704b88c807SRodney W. Grimes 	if (f_type)
1714b88c807SRodney W. Grimes 		colwidth += 1;
1724b88c807SRodney W. Grimes 
1734b88c807SRodney W. Grimes 	colwidth = (colwidth + TAB) & ~(TAB - 1);
1744b88c807SRodney W. Grimes 	if (termwidth < 2 * colwidth) {
1754b88c807SRodney W. Grimes 		printscol(dp);
1764b88c807SRodney W. Grimes 		return;
1774b88c807SRodney W. Grimes 	}
1784b88c807SRodney W. Grimes 
1794b88c807SRodney W. Grimes 	numcols = termwidth / colwidth;
1804b88c807SRodney W. Grimes 	numrows = num / numcols;
1814b88c807SRodney W. Grimes 	if (num % numcols)
1824b88c807SRodney W. Grimes 		++numrows;
1834b88c807SRodney W. Grimes 
1844b88c807SRodney W. Grimes 	if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
1854b88c807SRodney W. Grimes 		(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
1864b88c807SRodney W. Grimes 	for (row = 0; row < numrows; ++row) {
1874b88c807SRodney W. Grimes 		endcol = colwidth;
1884b88c807SRodney W. Grimes 		for (base = row, chcnt = col = 0; col < numcols; ++col) {
1894b88c807SRodney W. Grimes 			chcnt += printaname(array[base], dp->s_inode,
1904b88c807SRodney W. Grimes 			    dp->s_block);
1914b88c807SRodney W. Grimes 			if ((base += numrows) >= num)
1924b88c807SRodney W. Grimes 				break;
1930fd510b7SJoerg Wunsch 			while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol){
1944b88c807SRodney W. Grimes 				(void)putchar('\t');
1954b88c807SRodney W. Grimes 				chcnt = cnt;
1964b88c807SRodney W. Grimes 			}
1974b88c807SRodney W. Grimes 			endcol += colwidth;
1984b88c807SRodney W. Grimes 		}
1994b88c807SRodney W. Grimes 		(void)putchar('\n');
2004b88c807SRodney W. Grimes 	}
2014b88c807SRodney W. Grimes }
2024b88c807SRodney W. Grimes 
2034b88c807SRodney W. Grimes /*
2044b88c807SRodney W. Grimes  * print [inode] [size] name
2054b88c807SRodney W. Grimes  * return # of characters printed, no trailing characters.
2064b88c807SRodney W. Grimes  */
2074b88c807SRodney W. Grimes static int
2084b88c807SRodney W. Grimes printaname(p, inodefield, sizefield)
2094b88c807SRodney W. Grimes 	FTSENT *p;
2104b88c807SRodney W. Grimes 	u_long sizefield, inodefield;
2114b88c807SRodney W. Grimes {
2124b88c807SRodney W. Grimes 	struct stat *sp;
2134b88c807SRodney W. Grimes 	int chcnt;
2144b88c807SRodney W. Grimes 
2154b88c807SRodney W. Grimes 	sp = p->fts_statp;
2164b88c807SRodney W. Grimes 	chcnt = 0;
2174b88c807SRodney W. Grimes 	if (f_inode)
218fb5cb208SSteve Price 		chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino);
2194b88c807SRodney W. Grimes 	if (f_size)
2204b88c807SRodney W. Grimes 		chcnt += printf("%*qd ",
2214b88c807SRodney W. Grimes 		    (int)sizefield, howmany(sp->st_blocks, blocksize));
2224b88c807SRodney W. Grimes 	chcnt += printf("%s", p->fts_name);
2234b88c807SRodney W. Grimes 	if (f_type)
2244b88c807SRodney W. Grimes 		chcnt += printtype(sp->st_mode);
2254b88c807SRodney W. Grimes 	return (chcnt);
2264b88c807SRodney W. Grimes }
2274b88c807SRodney W. Grimes 
2284b88c807SRodney W. Grimes static void
2294b88c807SRodney W. Grimes printtime(ftime)
2304b88c807SRodney W. Grimes 	time_t ftime;
2314b88c807SRodney W. Grimes {
2324b88c807SRodney W. Grimes 	int i;
233fc4a9bafSAndrey A. Chernov 	char longstring[80];
2344b88c807SRodney W. Grimes 
235fc4a9bafSAndrey A. Chernov 	strftime(longstring, sizeof(longstring), "%c", localtime(&ftime));
2364b88c807SRodney W. Grimes 	for (i = 4; i < 11; ++i)
2374b88c807SRodney W. Grimes 		(void)putchar(longstring[i]);
2384b88c807SRodney W. Grimes 
239656dcd43SGarrett Wollman #define	SIXMONTHS	((365 / 2) * 86400)
2404b88c807SRodney W. Grimes 	if (f_sectime)
2414b88c807SRodney W. Grimes 		for (i = 11; i < 24; i++)
2424b88c807SRodney W. Grimes 			(void)putchar(longstring[i]);
2434b88c807SRodney W. Grimes 	else if (ftime + SIXMONTHS > time(NULL))
2444b88c807SRodney W. Grimes 		for (i = 11; i < 16; ++i)
2454b88c807SRodney W. Grimes 			(void)putchar(longstring[i]);
2464b88c807SRodney W. Grimes 	else {
2474b88c807SRodney W. Grimes 		(void)putchar(' ');
2484b88c807SRodney W. Grimes 		for (i = 20; i < 24; ++i)
2494b88c807SRodney W. Grimes 			(void)putchar(longstring[i]);
2504b88c807SRodney W. Grimes 	}
2514b88c807SRodney W. Grimes 	(void)putchar(' ');
2524b88c807SRodney W. Grimes }
2534b88c807SRodney W. Grimes 
2544b88c807SRodney W. Grimes static int
2554b88c807SRodney W. Grimes printtype(mode)
2564b88c807SRodney W. Grimes 	u_int mode;
2574b88c807SRodney W. Grimes {
2584b88c807SRodney W. Grimes 	switch (mode & S_IFMT) {
2594b88c807SRodney W. Grimes 	case S_IFDIR:
2604b88c807SRodney W. Grimes 		(void)putchar('/');
2614b88c807SRodney W. Grimes 		return (1);
2624b88c807SRodney W. Grimes 	case S_IFIFO:
2634b88c807SRodney W. Grimes 		(void)putchar('|');
2644b88c807SRodney W. Grimes 		return (1);
2654b88c807SRodney W. Grimes 	case S_IFLNK:
2664b88c807SRodney W. Grimes 		(void)putchar('@');
2674b88c807SRodney W. Grimes 		return (1);
2684b88c807SRodney W. Grimes 	case S_IFSOCK:
2694b88c807SRodney W. Grimes 		(void)putchar('=');
2704b88c807SRodney W. Grimes 		return (1);
271fb5cb208SSteve Price #ifndef BSD4_4_LITE
272fb5cb208SSteve Price 	case S_IFWHT:
273fb5cb208SSteve Price 		(void)putchar('%');
274fb5cb208SSteve Price 		return (1);
275fb5cb208SSteve Price #endif
2764b88c807SRodney W. Grimes 	}
2774b88c807SRodney W. Grimes 	if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
2784b88c807SRodney W. Grimes 		(void)putchar('*');
2794b88c807SRodney W. Grimes 		return (1);
2804b88c807SRodney W. Grimes 	}
2814b88c807SRodney W. Grimes 	return (0);
2824b88c807SRodney W. Grimes }
2834b88c807SRodney W. Grimes 
2844b88c807SRodney W. Grimes static void
2854b88c807SRodney W. Grimes printlink(p)
2864b88c807SRodney W. Grimes 	FTSENT *p;
2874b88c807SRodney W. Grimes {
2884b88c807SRodney W. Grimes 	int lnklen;
2894b88c807SRodney W. Grimes 	char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
2904b88c807SRodney W. Grimes 
2914b88c807SRodney W. Grimes 	if (p->fts_level == FTS_ROOTLEVEL)
2924b88c807SRodney W. Grimes 		(void)snprintf(name, sizeof(name), "%s", p->fts_name);
2934b88c807SRodney W. Grimes 	else
2944b88c807SRodney W. Grimes 		(void)snprintf(name, sizeof(name),
2954b88c807SRodney W. Grimes 		    "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
2964b88c807SRodney W. Grimes 	if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
2974b88c807SRodney W. Grimes 		(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
2984b88c807SRodney W. Grimes 		return;
2994b88c807SRodney W. Grimes 	}
3004b88c807SRodney W. Grimes 	path[lnklen] = '\0';
3014b88c807SRodney W. Grimes 	(void)printf(" -> %s", path);
3024b88c807SRodney W. Grimes }
303