first working version, checkpoint
[unix-history] / usr / src / bin / ls / print.c
CommitLineData
62a77e99
KB
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
eeb191cb
KB
5 * This code is derived from software contributed to Berkeley by
6 * Michael Fischbein.
7 *
62a77e99
KB
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the University of California, Berkeley. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 */
20
21#ifndef lint
9071313b 22static char sccsid[] = "@(#)print.c 5.7 (Berkeley) %G%";
62a77e99
KB
23#endif /* not lint */
24
25#include <sys/param.h>
26#include <sys/stat.h>
27#include <stdio.h>
28#include <grp.h>
29#include <pwd.h>
a1a213d1 30#include <utmp.h>
62a77e99
KB
31#include <tzfile.h>
32#include "ls.h"
33
75a967bb
KB
34printscol(stats, num)
35 register LS *stats;
62a77e99
KB
36 register int num;
37{
75a967bb
KB
38 for (; num--; ++stats) {
39 (void)printaname(stats);
40 (void)putchar('\n');
41 }
42}
43
44printlong(stats, num)
45 LS *stats;
46 register int num;
47{
eb8c7f67 48 (void)printf("total %lu\n", stats[0].lstat.st_flags);
75a967bb
KB
49 for (; num--; ++stats) {
50 if (f_inode)
51 (void)printf("%6lu ", stats->lstat.st_ino);
52 if (f_size)
53 (void)printf("%4ld ", stats->lstat.st_blocks / 2);
54 printperms(stats->lstat.st_mode);
55 (void)printf("%3d ", stats->lstat.st_nlink);
56 printowner(stats->lstat.st_uid);
57 if (f_group)
58 printgrp(stats->lstat.st_gid);
59 if (S_ISCHR(stats->lstat.st_mode) ||
60 S_ISBLK(stats->lstat.st_mode))
61 (void)printf("%3d,%4d ", major(stats->lstat.st_rdev),
62 minor(stats->lstat.st_rdev));
63 else
64 (void)printf("%8ld ", stats->lstat.st_size);
65 if (f_accesstime)
66 printtime(stats->lstat.st_atime);
67 else if (f_statustime)
68 printtime(stats->lstat.st_ctime);
69 else
70 printtime(stats->lstat.st_mtime);
71 (void)printf("%s", stats->name);
72 if (f_type)
73 (void)printtype(stats->lstat.st_mode);
74 if (S_ISLNK(stats->lstat.st_mode))
75 printlink(stats->name);
76 (void)putchar('\n');
77 }
78}
79
80printcol(stats, num)
81 LS *stats;
82 register int num;
83{
eb8c7f67 84 extern int termwidth;
9071313b 85 int row, col;
62a77e99
KB
86 int colwidth; /* width of a printing column */
87 int numcols; /* number of columns */
9071313b 88 int numrows; /* number of rows */
62a77e99 89 int base; /* subscript for leftmost column */
62a77e99 90 int chcnt; /* character count printed */
9071313b
KB
91 int newcnt;
92 int curcol;
62a77e99 93
9071313b 94 colwidth = stats[0].lstat.st_flags;
62a77e99 95 if (f_inode)
9071313b 96 colwidth += 6;
62a77e99 97 if (f_size)
9071313b 98 colwidth += 5;
62a77e99 99 if (f_type)
9071313b
KB
100 colwidth += 1;
101 colwidth += 3;
102
103 numcols = termwidth / colwidth;
104 numrows = num / numcols;
105 if (num % numcols)
106 ++numrows;
62a77e99 107
9071313b
KB
108#define TAB 8
109 for (row = 0; row < numrows; ++row) {
110 curcol = colwidth;
111 chcnt = 0;
112 for (base = row, col = 0; col < numcols; ++col) {
113 chcnt += printaname(stats + base);
114 if ((base += numrows) >= num)
62a77e99 115 break;
9071313b
KB
116 for (;;) {
117 newcnt = (chcnt + TAB & ~(TAB - 1));
118 if (newcnt > curcol) {
119 break;
62a77e99 120 }
9071313b
KB
121 (void)putchar('\t');
122 chcnt = newcnt;
62a77e99 123 }
9071313b
KB
124 for (; chcnt < curcol; ++chcnt)
125 (void)putchar(' ');
126 curcol += colwidth;
62a77e99 127 }
9071313b 128 putchar('\n');
62a77e99
KB
129 }
130}
131
132/*
133 * print [inode] [size] name
134 * return # of characters printed, no trailing characters
135 */
75a967bb
KB
136printaname(lp)
137 LS *lp;
62a77e99 138{
75a967bb 139 int chcnt;
62a77e99 140
75a967bb 141 chcnt = 0;
62a77e99 142 if (f_inode)
75a967bb 143 chcnt += printf("%5lu ", lp->lstat.st_ino);
62a77e99 144 if (f_size)
75a967bb
KB
145 chcnt += printf("%4ld ", lp->lstat.st_blocks / 2);
146 chcnt += printf("%s", lp->name);
62a77e99 147 if (f_type)
75a967bb 148 chcnt += printtype(lp->lstat.st_mode);
62a77e99
KB
149 return(chcnt);
150}
151
a1a213d1
KB
152#define NCACHE 64 /* power of 2 */
153#define LSMASK NCACHE - 1 /* bits to store with */
154printowner(uid)
155 uid_t uid;
62a77e99 156{
a1a213d1
KB
157 static struct ncache {
158 uid_t uid;
159 char name[UT_NAMESIZE];
160 } c_uid[NCACHE];
161 register struct passwd *pw;
162 register struct ncache *cp;
163
164 cp = c_uid + (uid & LSMASK);
165 if (cp->uid != uid || !*cp->name) {
166 /* if can't find owner, print out number instead */
167 if (!(pw = getpwuid(uid))) {
168 (void)printf("%-*.*u ", UT_NAMESIZE, UT_NAMESIZE, uid);
169 return;
170 }
171 cp->uid = uid;
172 (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
62a77e99 173 }
a1a213d1 174 (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, cp->name);
62a77e99
KB
175}
176
a1a213d1
KB
177printgrp(gid)
178 gid_t gid;
62a77e99 179{
a1a213d1
KB
180 static struct ncache {
181 gid_t gid;
182 char name[UT_NAMESIZE];
183 } c_gid[NCACHE];
184 register struct group *gr;
185 register struct ncache *cp;
186
187 cp = c_gid + (gid & LSMASK);
188 if (cp->gid != gid || *cp->name) {
189 /* can't find group, print out number instead */
190 if (!(gr = getgrgid(gid))) {
191 (void)printf("%-*.*u ", UT_NAMESIZE, UT_NAMESIZE, gid);
192 return;
193 }
194 cp->gid = gid;
195 (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
62a77e99 196 }
a1a213d1 197 (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, cp->name);
62a77e99
KB
198}
199
200printtime(ftime)
201 time_t ftime;
202{
203 int i;
204 char *longstring, *ctime();
205 time_t time();
206
207 longstring = ctime((long *)&ftime);
208 for (i = 4; i < 11; ++i)
209 (void)putchar(longstring[i]);
210
211#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
212 if (ftime + SIXMONTHS > time((time_t *)NULL))
213 for (i = 11; i < 16; ++i)
214 (void)putchar(longstring[i]);
215 else {
216 (void)putchar(' ');
217 for (i = 20; i < 24; ++i)
218 (void)putchar(longstring[i]);
219 }
220 (void)putchar(' ');
221}
222
223/*
224 * do the permissions printing, passed the mode
225 */
226printperms(mode)
227 mode_t mode;
228{
229 /* print type */
230 switch (mode & S_IFMT) {
231 case S_IFDIR: /* directory */
232 (void)putchar('d');
233 break;
234 case S_IFCHR: /* character special */
235 (void)putchar('c');
236 break;
237 case S_IFBLK: /* block special */
238 (void)putchar('b');
239 break;
240 case S_IFREG: /* regular */
241 (void)putchar('-');
242 break;
243 case S_IFLNK: /* symbolic link */
244 (void)putchar('l');
245 break;
246 case S_IFSOCK: /* socket */
247 (void)putchar('s');
248 break;
249#ifdef S_IFIFO
250 case S_IFIFO: /* fifo */
251 (void)putchar('p');
252 break;
253#endif
254 default: /* unknown */
255 (void)putchar('?');
256 break;
257 }
258 /* usr */
259 if (mode & S_IRUSR)
260 (void)putchar('r');
261 else
262 (void)putchar('-');
263 if (mode & S_IWUSR)
264 (void)putchar('w');
265 else
266 (void)putchar('-');
267 switch (mode & (S_IXUSR | S_ISUID)) {
268 case 0:
269 (void)putchar('-');
270 break;
271 case S_IXUSR:
272 (void)putchar('x');
273 break;
274 case S_ISUID:
275 (void)putchar('S');
276 break;
277 case S_IXUSR | S_ISUID:
278 (void)putchar('s');
279 break;
280 }
281 /* group */
282 if (mode & S_IRGRP)
283 (void)putchar('r');
284 else
285 (void)putchar('-');
286 if (mode & S_IWGRP)
287 (void)putchar('w');
288 else
289 (void)putchar('-');
290 switch (mode & (S_IXGRP | S_ISGID)) {
291 case 0:
292 (void)putchar('-');
293 break;
294 case S_IXGRP:
295 (void)putchar('x');
296 break;
297 case S_ISGID:
298 (void)putchar('S');
299 break;
300 case S_IXGRP | S_ISGID:
301 (void)putchar('s');
302 break;
303 }
304 /* other */
305 if (mode & S_IROTH)
306 (void)putchar('r');
307 else
308 (void)putchar('-');
309 if (mode & S_IWOTH)
310 (void)putchar('w');
311 else
312 (void)putchar('-');
313 switch (mode & (S_IXOTH | S_ISVTX)) {
314 case 0:
315 (void)putchar('-');
316 break;
317 case S_IXOTH:
318 (void)putchar('x');
319 break;
320 case S_ISVTX:
321 (void)putchar('T');
322 break;
323 case S_IXOTH | S_ISVTX:
324 (void)putchar('t');
325 break;
326 }
327}
328
329printtype(mode)
330 mode_t mode;
331{
332 switch(mode & S_IFMT) {
333 case S_IFDIR:
334 (void)putchar('/');
335 return(1);
336 case S_IFLNK:
337 (void)putchar('@');
338 return(1);
339 case S_IFSOCK:
340 (void)putchar('=');
341 return(1);
342 }
343 if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
344 (void)putchar('*');
345 return(1);
346 }
347 return(0);
348}
349
350printlink(name)
351 char *name;
352{
353 int lnklen;
354 char path[MAXPATHLEN + 1], *strerror();
355
356 if ((lnklen = readlink(name, path, MAXPATHLEN)) == -1) {
357 (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
358 return;
359 }
360 path[lnklen] = '\0';
361 (void)printf(" -> %s", path);
362}