add getwd/chdir for multiple directory operands
[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
45e87c19 22static char sccsid[] = "@(#)print.c 5.11 (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{
45e87c19 48 (void)printf("total %lu\n", stats[0].lstat.st_btotal);
75a967bb
KB
49 for (; num--; ++stats) {
50 if (f_inode)
51 (void)printf("%6lu ", stats->lstat.st_ino);
52 if (f_size)
05aeb2af 53 (void)printf("%4ld ", stats->lstat.st_blocks);
75a967bb
KB
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
3cc8e3ba
KB
80#define TAB 8
81
75a967bb
KB
82printcol(stats, num)
83 LS *stats;
67e8527c 84 int num;
75a967bb 85{
eb8c7f67 86 extern int termwidth;
3cc8e3ba
KB
87 register int base, chcnt, cnt, col, colwidth;
88 int endcol, numcols, numrows, row;
62a77e99 89
45e87c19 90 colwidth = stats[0].lstat.st_maxlen;
62a77e99 91 if (f_inode)
9071313b 92 colwidth += 6;
62a77e99 93 if (f_size)
9071313b 94 colwidth += 5;
62a77e99 95 if (f_type)
9071313b 96 colwidth += 1;
3cc8e3ba 97 colwidth = (colwidth + TAB) & ~(TAB - 1);
9071313b
KB
98
99 numcols = termwidth / colwidth;
100 numrows = num / numcols;
101 if (num % numcols)
102 ++numrows;
62a77e99 103
45e87c19
KB
104 if (f_size)
105 (void)printf("total %lu\n", stats[0].lstat.st_btotal);
9071313b 106 for (row = 0; row < numrows; ++row) {
67e8527c
KB
107 endcol = colwidth;
108 for (base = row, chcnt = col = 0; col < numcols; ++col) {
9071313b
KB
109 chcnt += printaname(stats + base);
110 if ((base += numrows) >= num)
62a77e99 111 break;
67e8527c 112 while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
9071313b 113 (void)putchar('\t');
67e8527c 114 chcnt = cnt;
62a77e99 115 }
67e8527c 116 endcol += colwidth;
62a77e99 117 }
9071313b 118 putchar('\n');
62a77e99
KB
119 }
120}
121
122/*
123 * print [inode] [size] name
124 * return # of characters printed, no trailing characters
125 */
75a967bb
KB
126printaname(lp)
127 LS *lp;
62a77e99 128{
75a967bb 129 int chcnt;
62a77e99 130
75a967bb 131 chcnt = 0;
62a77e99 132 if (f_inode)
75a967bb 133 chcnt += printf("%5lu ", lp->lstat.st_ino);
62a77e99 134 if (f_size)
05aeb2af 135 chcnt += printf("%4ld ", lp->lstat.st_blocks);
75a967bb 136 chcnt += printf("%s", lp->name);
62a77e99 137 if (f_type)
75a967bb 138 chcnt += printtype(lp->lstat.st_mode);
62a77e99
KB
139 return(chcnt);
140}
141
a1a213d1
KB
142#define NCACHE 64 /* power of 2 */
143#define LSMASK NCACHE - 1 /* bits to store with */
144printowner(uid)
145 uid_t uid;
62a77e99 146{
a1a213d1
KB
147 static struct ncache {
148 uid_t uid;
149 char name[UT_NAMESIZE];
150 } c_uid[NCACHE];
151 register struct passwd *pw;
152 register struct ncache *cp;
153
154 cp = c_uid + (uid & LSMASK);
155 if (cp->uid != uid || !*cp->name) {
156 /* if can't find owner, print out number instead */
157 if (!(pw = getpwuid(uid))) {
158 (void)printf("%-*.*u ", UT_NAMESIZE, UT_NAMESIZE, uid);
159 return;
160 }
161 cp->uid = uid;
162 (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE);
62a77e99 163 }
a1a213d1 164 (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, cp->name);
62a77e99
KB
165}
166
a1a213d1
KB
167printgrp(gid)
168 gid_t gid;
62a77e99 169{
a1a213d1
KB
170 static struct ncache {
171 gid_t gid;
172 char name[UT_NAMESIZE];
173 } c_gid[NCACHE];
174 register struct group *gr;
175 register struct ncache *cp;
176
177 cp = c_gid + (gid & LSMASK);
178 if (cp->gid != gid || *cp->name) {
179 /* can't find group, print out number instead */
180 if (!(gr = getgrgid(gid))) {
181 (void)printf("%-*.*u ", UT_NAMESIZE, UT_NAMESIZE, gid);
182 return;
183 }
184 cp->gid = gid;
185 (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE);
62a77e99 186 }
a1a213d1 187 (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, cp->name);
62a77e99
KB
188}
189
190printtime(ftime)
191 time_t ftime;
192{
193 int i;
194 char *longstring, *ctime();
195 time_t time();
196
197 longstring = ctime((long *)&ftime);
198 for (i = 4; i < 11; ++i)
199 (void)putchar(longstring[i]);
200
201#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
202 if (ftime + SIXMONTHS > time((time_t *)NULL))
203 for (i = 11; i < 16; ++i)
204 (void)putchar(longstring[i]);
205 else {
206 (void)putchar(' ');
207 for (i = 20; i < 24; ++i)
208 (void)putchar(longstring[i]);
209 }
210 (void)putchar(' ');
211}
212
213/*
214 * do the permissions printing, passed the mode
215 */
216printperms(mode)
217 mode_t mode;
218{
219 /* print type */
220 switch (mode & S_IFMT) {
221 case S_IFDIR: /* directory */
222 (void)putchar('d');
223 break;
224 case S_IFCHR: /* character special */
225 (void)putchar('c');
226 break;
227 case S_IFBLK: /* block special */
228 (void)putchar('b');
229 break;
230 case S_IFREG: /* regular */
231 (void)putchar('-');
232 break;
233 case S_IFLNK: /* symbolic link */
234 (void)putchar('l');
235 break;
236 case S_IFSOCK: /* socket */
237 (void)putchar('s');
238 break;
239#ifdef S_IFIFO
240 case S_IFIFO: /* fifo */
241 (void)putchar('p');
242 break;
243#endif
244 default: /* unknown */
245 (void)putchar('?');
246 break;
247 }
248 /* usr */
249 if (mode & S_IRUSR)
250 (void)putchar('r');
251 else
252 (void)putchar('-');
253 if (mode & S_IWUSR)
254 (void)putchar('w');
255 else
256 (void)putchar('-');
257 switch (mode & (S_IXUSR | S_ISUID)) {
258 case 0:
259 (void)putchar('-');
260 break;
261 case S_IXUSR:
262 (void)putchar('x');
263 break;
264 case S_ISUID:
265 (void)putchar('S');
266 break;
267 case S_IXUSR | S_ISUID:
268 (void)putchar('s');
269 break;
270 }
271 /* group */
272 if (mode & S_IRGRP)
273 (void)putchar('r');
274 else
275 (void)putchar('-');
276 if (mode & S_IWGRP)
277 (void)putchar('w');
278 else
279 (void)putchar('-');
280 switch (mode & (S_IXGRP | S_ISGID)) {
281 case 0:
282 (void)putchar('-');
283 break;
284 case S_IXGRP:
285 (void)putchar('x');
286 break;
287 case S_ISGID:
288 (void)putchar('S');
289 break;
290 case S_IXGRP | S_ISGID:
291 (void)putchar('s');
292 break;
293 }
294 /* other */
295 if (mode & S_IROTH)
296 (void)putchar('r');
297 else
298 (void)putchar('-');
299 if (mode & S_IWOTH)
300 (void)putchar('w');
301 else
302 (void)putchar('-');
303 switch (mode & (S_IXOTH | S_ISVTX)) {
304 case 0:
305 (void)putchar('-');
306 break;
307 case S_IXOTH:
308 (void)putchar('x');
309 break;
310 case S_ISVTX:
311 (void)putchar('T');
312 break;
313 case S_IXOTH | S_ISVTX:
314 (void)putchar('t');
315 break;
316 }
317}
318
319printtype(mode)
320 mode_t mode;
321{
322 switch(mode & S_IFMT) {
323 case S_IFDIR:
324 (void)putchar('/');
325 return(1);
326 case S_IFLNK:
327 (void)putchar('@');
328 return(1);
329 case S_IFSOCK:
330 (void)putchar('=');
331 return(1);
332 }
333 if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
334 (void)putchar('*');
335 return(1);
336 }
337 return(0);
338}
339
340printlink(name)
341 char *name;
342{
343 int lnklen;
344 char path[MAXPATHLEN + 1], *strerror();
345
346 if ((lnklen = readlink(name, path, MAXPATHLEN)) == -1) {
347 (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
348 return;
349 }
350 path[lnklen] = '\0';
351 (void)printf(" -> %s", path);
352}