xref: /original-bsd/bin/ls/print.c (revision c74f8e57)
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 %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)print.c	5.20 (Berkeley) 04/08/90";
13 #endif /* not lint */
14 
15 #include <sys/param.h>
16 #include <sys/stat.h>
17 #include <stdio.h>
18 #include <grp.h>
19 #include <pwd.h>
20 #include <utmp.h>
21 #include <tzfile.h>
22 #include "ls.h"
23 
24 printscol(stats, num)
25 	register LS *stats;
26 	register int num;
27 {
28 	for (; num--; ++stats) {
29 		(void)printaname(stats);
30 		(void)putchar('\n');
31 	}
32 }
33 
34 printlong(stats, num)
35 	LS *stats;
36 	register int num;
37 {
38 	char *user_from_uid(), *group_from_gid();
39 
40 	if (f_total)
41 		(void)printf("total %lu\n", f_kblocks ?
42 		    howmany(stats[0].lstat.st_btotal, 2) :
43 		    stats[0].lstat.st_btotal);
44 	for (; num--; ++stats) {
45 		if (f_inode)
46 			(void)printf("%6lu ", stats->lstat.st_ino);
47 		if (f_size)
48 			(void)printf("%4ld ", f_kblocks ?
49 			    howmany(stats->lstat.st_blocks, 2) :
50 			    stats->lstat.st_blocks);
51 		printperms(stats->lstat.st_mode);
52 		(void)printf("%3u %-*s ", stats->lstat.st_nlink, UT_NAMESIZE,
53 		    user_from_uid(stats->lstat.st_uid, 0));
54 		if (f_group)
55 			(void)printf("%-*s ", UT_NAMESIZE,
56 			    group_from_gid(stats->lstat.st_gid, 0));
57 		if (S_ISCHR(stats->lstat.st_mode) ||
58 		    S_ISBLK(stats->lstat.st_mode))
59 			(void)printf("%3d, %3d ", major(stats->lstat.st_rdev),
60 			    minor(stats->lstat.st_rdev));
61 		else
62 			(void)printf("%8ld ", stats->lstat.st_size);
63 		if (f_accesstime)
64 			printtime(stats->lstat.st_atime);
65 		else if (f_statustime)
66 			printtime(stats->lstat.st_ctime);
67 		else
68 			printtime(stats->lstat.st_mtime);
69 		(void)printf("%s", stats->name);
70 		if (f_type)
71 			(void)printtype(stats->lstat.st_mode);
72 		if (S_ISLNK(stats->lstat.st_mode))
73 			printlink(stats->name);
74 		(void)putchar('\n');
75 	}
76 }
77 
78 #define	TAB	8
79 
80 printcol(stats, num)
81 	LS *stats;
82 	int num;
83 {
84 	extern int termwidth;
85 	register int base, chcnt, cnt, col, colwidth;
86 	int endcol, numcols, numrows, row;
87 
88 	colwidth = stats[0].lstat.st_maxlen;
89 	if (f_inode)
90 		colwidth += 6;
91 	if (f_size)
92 		colwidth += 5;
93 	if (f_type)
94 		colwidth += 1;
95 
96 	colwidth = (colwidth + TAB) & ~(TAB - 1);
97 	if (termwidth < 2 * colwidth) {
98 		printscol(stats, num);
99 		return;
100 	}
101 
102 	numcols = termwidth / colwidth;
103 	numrows = num / numcols;
104 	if (num % numcols)
105 		++numrows;
106 
107 	if (f_size && f_total)
108 		(void)printf("total %lu\n", f_kblocks ?
109 		    howmany(stats[0].lstat.st_btotal, 2) :
110 		    stats[0].lstat.st_btotal);
111 	for (row = 0; row < numrows; ++row) {
112 		endcol = colwidth;
113 		for (base = row, chcnt = col = 0; col < numcols; ++col) {
114 			chcnt += printaname(stats + base);
115 			if ((base += numrows) >= num)
116 				break;
117 			while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
118 				(void)putchar('\t');
119 				chcnt = cnt;
120 			}
121 			endcol += colwidth;
122 		}
123 		putchar('\n');
124 	}
125 }
126 
127 /*
128  * print [inode] [size] name
129  * return # of characters printed, no trailing characters
130  */
131 printaname(lp)
132 	LS *lp;
133 {
134 	int chcnt;
135 
136 	chcnt = 0;
137 	if (f_inode)
138 		chcnt += printf("%5lu ", lp->lstat.st_ino);
139 	if (f_size)
140 		chcnt += printf("%4ld ", f_kblocks ?
141 		    howmany(lp->lstat.st_blocks, 2) : lp->lstat.st_blocks);
142 	chcnt += printf("%s", lp->name);
143 	if (f_type)
144 		chcnt += printtype(lp->lstat.st_mode);
145 	return(chcnt);
146 }
147 
148 printtime(ftime)
149 	time_t ftime;
150 {
151 	int i;
152 	char *longstring, *ctime();
153 	time_t time();
154 
155 	longstring = ctime((long *)&ftime);
156 	for (i = 4; i < 11; ++i)
157 		(void)putchar(longstring[i]);
158 
159 #define	SIXMONTHS	((DAYSPERNYEAR / 2) * SECSPERDAY)
160 	if (ftime + SIXMONTHS > time((time_t *)NULL))
161 		for (i = 11; i < 16; ++i)
162 			(void)putchar(longstring[i]);
163 	else {
164 		(void)putchar(' ');
165 		for (i = 20; i < 24; ++i)
166 			(void)putchar(longstring[i]);
167 	}
168 	(void)putchar(' ');
169 }
170 
171 /*
172  * do the permissions printing, passed the mode
173  */
174 printperms(mode)
175 	mode_t mode;
176 {
177 	 /* print type */
178 	switch (mode & S_IFMT) {
179 	case S_IFDIR:			/* directory */
180 		(void)putchar('d');
181 		break;
182 	case S_IFCHR:			/* character special */
183 		(void)putchar('c');
184 		break;
185 	case S_IFBLK:			/* block special */
186 		(void)putchar('b');
187 		break;
188 	case S_IFREG:			/* regular */
189 		(void)putchar('-');
190 		break;
191 	case S_IFLNK:			/* symbolic link */
192 		(void)putchar('l');
193 		break;
194 	case S_IFSOCK:			/* socket */
195 		(void)putchar('s');
196 		break;
197 #ifdef S_IFIFO
198 	case S_IFIFO:			/* fifo */
199 		(void)putchar('p');
200 		break;
201 #endif
202 	default:			/* unknown */
203 		(void)putchar('?');
204 		break;
205 	}
206 	/* usr */
207 	if (mode & S_IRUSR)
208 		(void)putchar('r');
209 	else
210 		(void)putchar('-');
211 	if (mode & S_IWUSR)
212 		(void)putchar('w');
213 	else
214 		(void)putchar('-');
215 	switch (mode & (S_IXUSR | S_ISUID)) {
216 	case 0:
217 		(void)putchar('-');
218 		break;
219 	case S_IXUSR:
220 		(void)putchar('x');
221 		break;
222 	case S_ISUID:
223 		(void)putchar('S');
224 		break;
225 	case S_IXUSR | S_ISUID:
226 		(void)putchar('s');
227 		break;
228 	}
229 	/* group */
230 	if (mode & S_IRGRP)
231 		(void)putchar('r');
232 	else
233 		(void)putchar('-');
234 	if (mode & S_IWGRP)
235 		(void)putchar('w');
236 	else
237 		(void)putchar('-');
238 	switch (mode & (S_IXGRP | S_ISGID)) {
239 	case 0:
240 		(void)putchar('-');
241 		break;
242 	case S_IXGRP:
243 		(void)putchar('x');
244 		break;
245 	case S_ISGID:
246 		(void)putchar('S');
247 		break;
248 	case S_IXGRP | S_ISGID:
249 		(void)putchar('s');
250 		break;
251 	}
252 	/* other */
253 	if (mode & S_IROTH)
254 		(void)putchar('r');
255 	else
256 		(void)putchar('-');
257 	if (mode & S_IWOTH)
258 		(void)putchar('w');
259 	else
260 		(void)putchar('-');
261 	switch (mode & (S_IXOTH | S_ISVTX)) {
262 	case 0:
263 		(void)putchar('-');
264 		break;
265 	case S_IXOTH:
266 		(void)putchar('x');
267 		break;
268 	case S_ISVTX:
269 		(void)putchar('T');
270 		break;
271 	case S_IXOTH | S_ISVTX:
272 		(void)putchar('t');
273 		break;
274 	}
275 	(void)putchar(' ');
276 }
277 
278 printtype(mode)
279 	mode_t mode;
280 {
281 	switch(mode & S_IFMT) {
282 	case S_IFDIR:
283 		(void)putchar('/');
284 		return(1);
285 	case S_IFLNK:
286 		(void)putchar('@');
287 		return(1);
288 	case S_IFSOCK:
289 		(void)putchar('=');
290 		return(1);
291 	}
292 	if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
293 		(void)putchar('*');
294 		return(1);
295 	}
296 	return(0);
297 }
298 
299 printlink(name)
300 	char *name;
301 {
302 	int lnklen;
303 	char path[MAXPATHLEN + 1], *strerror();
304 
305 	if ((lnklen = readlink(name, path, MAXPATHLEN)) == -1) {
306 		(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
307 		return;
308 	}
309 	path[lnklen] = '\0';
310 	(void)printf(" -> %s", path);
311 }
312