xref: /386bsd/usr/src/bin/ls/print.c (revision a2142627)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Michael Fischbein.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 static char sccsid[] = "@(#)print.c	5.24 (Berkeley) 10/19/90";
39 #endif /* not lint */
40 
41 #include <sys/param.h>
42 #include <sys/stat.h>
43 #include <stdio.h>
44 #include <grp.h>
45 #include <pwd.h>
46 #include <utmp.h>
47 #include <tzfile.h>
48 #include "ls.h"
49 
printscol(stats,num)50 printscol(stats, num)
51 	register LS *stats;
52 	register int num;
53 {
54 	for (; num--; ++stats) {
55 		(void)printaname(stats);
56 		(void)putchar('\n');
57 	}
58 }
59 
printlong(stats,num)60 printlong(stats, num)
61 	LS *stats;
62 	register int num;
63 {
64 	extern int errno;
65 	char modep[15], *user_from_uid(), *group_from_gid(), *strerror();
66 
67 	if (f_total)
68 		(void)printf("total %lu\n", f_kblocks ?
69 		    howmany(stats[0].lstat.st_btotal, 2) :
70 		    stats[0].lstat.st_btotal);
71 	for (; num--; ++stats) {
72 		if (f_inode)
73 			(void)printf("%6lu ", stats->lstat.st_ino);
74 		if (f_size)
75 			(void)printf("%4ld ", f_kblocks ?
76 			    howmany(stats->lstat.st_blocks, 2) :
77 			    stats->lstat.st_blocks);
78 		(void)strmode(stats->lstat.st_mode, modep);
79 		(void)printf("%s %3u %-*s ", modep, stats->lstat.st_nlink,
80 		    UT_NAMESIZE, user_from_uid(stats->lstat.st_uid, 0));
81 		if (f_group)
82 			(void)printf("%-*s ", UT_NAMESIZE,
83 			    group_from_gid(stats->lstat.st_gid, 0));
84 		if (S_ISCHR(stats->lstat.st_mode) ||
85 		    S_ISBLK(stats->lstat.st_mode))
86 			(void)printf("%3d, %3d ", major(stats->lstat.st_rdev),
87 			    minor(stats->lstat.st_rdev));
88 		else
89 			(void)printf("%8ld ", stats->lstat.st_size);
90 		if (f_accesstime)
91 			printtime(stats->lstat.st_atime);
92 		else if (f_statustime)
93 			printtime(stats->lstat.st_ctime);
94 		else
95 			printtime(stats->lstat.st_mtime);
96 		(void)printf("%s", stats->name);
97 		if (f_type)
98 			(void)printtype(stats->lstat.st_mode);
99 		if (S_ISLNK(stats->lstat.st_mode))
100 			printlink(stats->name);
101 		(void)putchar('\n');
102 	}
103 }
104 
105 #define	TAB	8
106 
printcol(stats,num)107 printcol(stats, num)
108 	LS *stats;
109 	int num;
110 {
111 	extern int termwidth;
112 	register int base, chcnt, cnt, col, colwidth;
113 	int endcol, numcols, numrows, row;
114 
115 	colwidth = stats[0].lstat.st_maxlen;
116 	if (f_inode)
117 		colwidth += 6;
118 	if (f_size)
119 		colwidth += 5;
120 	if (f_type)
121 		colwidth += 1;
122 
123 	colwidth = (colwidth + TAB) & ~(TAB - 1);
124 	if (termwidth < 2 * colwidth) {
125 		printscol(stats, num);
126 		return;
127 	}
128 
129 	numcols = termwidth / colwidth;
130 	numrows = num / numcols;
131 	if (num % numcols)
132 		++numrows;
133 
134 	if (f_size && f_total)
135 		(void)printf("total %lu\n", f_kblocks ?
136 		    howmany(stats[0].lstat.st_btotal, 2) :
137 		    stats[0].lstat.st_btotal);
138 	for (row = 0; row < numrows; ++row) {
139 		endcol = colwidth;
140 		for (base = row, chcnt = col = 0; col < numcols; ++col) {
141 			chcnt += printaname(stats + base);
142 			if ((base += numrows) >= num)
143 				break;
144 			while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
145 				(void)putchar('\t');
146 				chcnt = cnt;
147 			}
148 			endcol += colwidth;
149 		}
150 		putchar('\n');
151 	}
152 }
153 
154 /*
155  * print [inode] [size] name
156  * return # of characters printed, no trailing characters
157  */
printaname(lp)158 printaname(lp)
159 	LS *lp;
160 {
161 	int chcnt;
162 
163 	chcnt = 0;
164 	if (f_inode)
165 		chcnt += printf("%5lu ", lp->lstat.st_ino);
166 	if (f_size)
167 		chcnt += printf("%4ld ", f_kblocks ?
168 		    howmany(lp->lstat.st_blocks, 2) : lp->lstat.st_blocks);
169 	chcnt += printf("%s", lp->name);
170 	if (f_type)
171 		chcnt += printtype(lp->lstat.st_mode);
172 	return(chcnt);
173 }
174 
printtime(ftime)175 printtime(ftime)
176 	time_t ftime;
177 {
178 	int i;
179 	char *longstring, *ctime();
180 	time_t time();
181 
182 	longstring = ctime((long *)&ftime);
183 	for (i = 4; i < 11; ++i)
184 		(void)putchar(longstring[i]);
185 
186 #define	SIXMONTHS	((DAYSPERNYEAR / 2) * SECSPERDAY)
187 	if (f_sectime)
188 		for (i = 11; i < 24; i++)
189 			(void)putchar(longstring[i]);
190 	else if (ftime + SIXMONTHS > time((time_t *)NULL))
191 		for (i = 11; i < 16; ++i)
192 			(void)putchar(longstring[i]);
193 	else {
194 		(void)putchar(' ');
195 		for (i = 20; i < 24; ++i)
196 			(void)putchar(longstring[i]);
197 	}
198 	(void)putchar(' ');
199 }
200 
printtype(mode)201 printtype(mode)
202 	mode_t mode;
203 {
204 	switch(mode & S_IFMT) {
205 	case S_IFDIR:
206 		(void)putchar('/');
207 		return(1);
208 	case S_IFLNK:
209 		(void)putchar('@');
210 		return(1);
211 	case S_IFSOCK:
212 		(void)putchar('=');
213 		return(1);
214 	}
215 	if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
216 		(void)putchar('*');
217 		return(1);
218 	}
219 	return(0);
220 }
221 
printlink(name)222 printlink(name)
223 	char *name;
224 {
225 	int lnklen;
226 	char path[PATH_MAX + 1], *strerror();
227 
228 	if ((lnklen = readlink(name, path, PATH_MAX)) == -1) {
229 		(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
230 		return;
231 	}
232 	path[lnklen] = '\0';
233 	(void)printf(" -> %s", path);
234 }
235