xref: /original-bsd/bin/ls/print.c (revision e3fc45e1)
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.27 (Berkeley) 12/12/91";
13 #endif /* not lint */
14 
15 #include <sys/param.h>
16 #include <sys/stat.h>
17 #include <time.h>
18 #include <errno.h>
19 #include <grp.h>
20 #include <pwd.h>
21 #include <utmp.h>
22 #include <tzfile.h>
23 #include <stdio.h>
24 #include "ls.h"
25 #include "extern.h"
26 
27 static int	printaname __P((LS *));
28 static void	printlink __P((char *));
29 static void	printtime __P((time_t));
30 static int	printtype __P((u_int));
31 static char	*flags_from_fid __P((long));
32 
33 void
34 printscol(stats, num)
35 	register LS *stats;
36 	register int num;
37 {
38 	for (; num--; ++stats) {
39 		(void)printaname(stats);
40 		(void)putchar('\n');
41 	}
42 }
43 
44 void
45 printlong(stats, num)
46 	LS *stats;
47 	register int num;
48 {
49 	char modep[15], *user_from_uid(), *group_from_gid();
50 
51 	if (f_total)
52 		(void)printf("total %lu\n", f_kblocks ?
53 		    howmany(stats[0].lstat.st_btotal, 2) :
54 		    stats[0].lstat.st_btotal);
55 	for (; num--; ++stats) {
56 		if (f_inode)
57 			(void)printf("%6lu ", stats->lstat.st_ino);
58 		if (f_size)
59 			(void)printf("%4ld ", f_kblocks ?
60 			    howmany(stats->lstat.st_blocks, 2) :
61 			    stats->lstat.st_blocks);
62 		(void)strmode(stats->lstat.st_mode, modep);
63 		(void)printf("%s %3u %-*s ", modep, stats->lstat.st_nlink,
64 		    UT_NAMESIZE, user_from_uid(stats->lstat.st_uid, 0));
65 		if (f_group)
66 			(void)printf("%-*s ", UT_NAMESIZE,
67 			    group_from_gid(stats->lstat.st_gid, 0));
68 		if (f_flags)
69 			(void)printf("%-*s ", FLAGSWIDTH,
70 			    flags_from_fid(stats->lstat.st_flags));
71 		if (S_ISCHR(stats->lstat.st_mode) ||
72 		    S_ISBLK(stats->lstat.st_mode))
73 			(void)printf("%3d, %3d ", major(stats->lstat.st_rdev),
74 			    minor(stats->lstat.st_rdev));
75 		else
76 			(void)printf("%8ld ", stats->lstat.st_size);
77 		if (f_accesstime)
78 			printtime(stats->lstat.st_atime);
79 		else if (f_statustime)
80 			printtime(stats->lstat.st_ctime);
81 		else
82 			printtime(stats->lstat.st_mtime);
83 		(void)printf("%s", stats->name);
84 		if (f_type)
85 			(void)printtype(stats->lstat.st_mode);
86 		if (S_ISLNK(stats->lstat.st_mode))
87 			printlink(stats->name);
88 		(void)putchar('\n');
89 	}
90 }
91 
92 #define	TAB	8
93 
94 void
95 printcol(stats, num)
96 	LS *stats;
97 	int num;
98 {
99 	extern int termwidth;
100 	register int base, chcnt, cnt, col, colwidth;
101 	int endcol, numcols, numrows, row;
102 
103 	colwidth = stats[0].lstat.st_maxlen;
104 	if (f_inode)
105 		colwidth += 6;
106 	if (f_size)
107 		colwidth += 5;
108 	if (f_type)
109 		colwidth += 1;
110 
111 	colwidth = (colwidth + TAB) & ~(TAB - 1);
112 	if (termwidth < 2 * colwidth) {
113 		printscol(stats, num);
114 		return;
115 	}
116 
117 	numcols = termwidth / colwidth;
118 	numrows = num / numcols;
119 	if (num % numcols)
120 		++numrows;
121 
122 	if (f_size && f_total)
123 		(void)printf("total %lu\n", f_kblocks ?
124 		    howmany(stats[0].lstat.st_btotal, 2) :
125 		    stats[0].lstat.st_btotal);
126 	for (row = 0; row < numrows; ++row) {
127 		endcol = colwidth;
128 		for (base = row, chcnt = col = 0; col < numcols; ++col) {
129 			chcnt += printaname(stats + base);
130 			if ((base += numrows) >= num)
131 				break;
132 			while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
133 				(void)putchar('\t');
134 				chcnt = cnt;
135 			}
136 			endcol += colwidth;
137 		}
138 		putchar('\n');
139 	}
140 }
141 
142 /*
143  * print [inode] [size] name
144  * return # of characters printed, no trailing characters
145  */
146 static int
147 printaname(lp)
148 	LS *lp;
149 {
150 	int chcnt;
151 
152 	chcnt = 0;
153 	if (f_inode)
154 		chcnt += printf("%5lu ", lp->lstat.st_ino);
155 	if (f_size)
156 		chcnt += printf("%4ld ", f_kblocks ?
157 		    howmany(lp->lstat.st_blocks, 2) : lp->lstat.st_blocks);
158 	chcnt += printf("%s", lp->name);
159 	if (f_type)
160 		chcnt += printtype(lp->lstat.st_mode);
161 	return (chcnt);
162 }
163 
164 static void
165 printtime(ftime)
166 	time_t ftime;
167 {
168 	int i;
169 	char *longstring;
170 
171 	longstring = ctime((time_t *)&ftime);
172 	for (i = 4; i < 11; ++i)
173 		(void)putchar(longstring[i]);
174 
175 #define	SIXMONTHS	((DAYSPERNYEAR / 2) * SECSPERDAY)
176 	if (f_sectime)
177 		for (i = 11; i < 24; i++)
178 			(void)putchar(longstring[i]);
179 	else if (ftime + SIXMONTHS > time((time_t *)NULL))
180 		for (i = 11; i < 16; ++i)
181 			(void)putchar(longstring[i]);
182 	else {
183 		(void)putchar(' ');
184 		for (i = 20; i < 24; ++i)
185 			(void)putchar(longstring[i]);
186 	}
187 	(void)putchar(' ');
188 }
189 
190 static int
191 printtype(mode)
192 	u_int mode;
193 {
194 	switch(mode & S_IFMT) {
195 	case S_IFDIR:
196 		(void)putchar('/');
197 		return (1);
198 	case S_IFLNK:
199 		(void)putchar('@');
200 		return (1);
201 	case S_IFSOCK:
202 		(void)putchar('=');
203 		return (1);
204 	}
205 	if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
206 		(void)putchar('*');
207 		return (1);
208 	}
209 	return (0);
210 }
211 
212 static void
213 printlink(name)
214 	char *name;
215 {
216 	int lnklen;
217 	char path[MAXPATHLEN + 1];
218 
219 	if ((lnklen = readlink(name, path, MAXPATHLEN)) == -1) {
220 		(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
221 		return;
222 	}
223 	path[lnklen] = '\0';
224 	(void)printf(" -> %s", path);
225 }
226 
227 static char *
228 flags_from_fid(flags)
229 	long flags;
230 {
231 	static char buf[FLAGSWIDTH + 1];
232 	int size;
233 
234 	size = FLAGSWIDTH;
235 	buf[0] = '\0';
236 	if (size && (flags & NODUMP)) {
237 		strncat(buf, "nodump", size);
238 		size -= 6;
239 	} else {
240 		strncat(buf, "dump", size);
241 		size -= 4;
242 	}
243 	if (size && (flags & IMMUTABLE)) {
244 		strncat(buf, ",nochg", size);
245 		size -= 6;
246 	}
247 	if (size && (flags & ARCHIVED)) {
248 		strncat(buf, ",arch", size);
249 		size -= 5;
250 	}
251 	return (buf);
252 }
253