Commit | Line | Data |
---|---|---|
62a77e99 | 1 | /* |
2eadf6d5 KM |
2 | * Copyright (c) 1989, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
62a77e99 | 4 | * |
eeb191cb KB |
5 | * This code is derived from software contributed to Berkeley by |
6 | * Michael Fischbein. | |
7 | * | |
0ce0ae04 | 8 | * %sccs.include.redist.c% |
62a77e99 KB |
9 | */ |
10 | ||
11 | #ifndef lint | |
706c0358 | 12 | static char sccsid[] = "@(#)print.c 8.2 (Berkeley) %G%"; |
62a77e99 KB |
13 | #endif /* not lint */ |
14 | ||
15 | #include <sys/param.h> | |
16 | #include <sys/stat.h> | |
77c06a9f KB |
17 | |
18 | #include <err.h> | |
0ce0ae04 | 19 | #include <errno.h> |
77c06a9f | 20 | #include <fts.h> |
62a77e99 KB |
21 | #include <grp.h> |
22 | #include <pwd.h> | |
0ce0ae04 | 23 | #include <stdio.h> |
77c06a9f | 24 | #include <stdlib.h> |
b651adfd | 25 | #include <string.h> |
77c06a9f KB |
26 | #include <time.h> |
27 | #include <tzfile.h> | |
28 | #include <unistd.h> | |
29 | #include <utmp.h> | |
30 | ||
62a77e99 | 31 | #include "ls.h" |
0ce0ae04 | 32 | #include "extern.h" |
d22495b4 | 33 | |
abe0683d EA |
34 | static int printaname __P((FTSENT *, u_long, u_long)); |
35 | static void printlink __P((FTSENT *)); | |
36 | static void printtime __P((time_t)); | |
37 | static int printtype __P((u_int)); | |
38 | ||
39 | #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) | |
62a77e99 | 40 | |
0ce0ae04 | 41 | void |
abe0683d EA |
42 | printscol(dp) |
43 | DISPLAY *dp; | |
62a77e99 | 44 | { |
706c0358 | 45 | FTSENT *p; |
d22495b4 | 46 | |
abe0683d EA |
47 | for (p = dp->list; p; p = p->fts_link) { |
48 | if (IS_NOPRINT(p)) | |
49 | continue; | |
50 | (void)printaname(p, dp->s_inode, dp->s_block); | |
51 | (void)putchar('\n'); | |
52 | } | |
75a967bb KB |
53 | } |
54 | ||
0ce0ae04 | 55 | void |
abe0683d EA |
56 | printlong(dp) |
57 | DISPLAY *dp; | |
75a967bb | 58 | { |
706c0358 JSP |
59 | struct stat *sp; |
60 | FTSENT *p; | |
abe0683d EA |
61 | NAMES *np; |
62 | char buf[20]; | |
63 | ||
64 | if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) | |
65 | (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); | |
66 | ||
67 | for (p = dp->list; p; p = p->fts_link) { | |
d22495b4 EA |
68 | if (IS_NOPRINT(p)) |
69 | continue; | |
70 | sp = p->fts_statp; | |
75a967bb | 71 | if (f_inode) |
abe0683d | 72 | (void)printf("%*lu ", dp->s_inode, sp->st_ino); |
75a967bb | 73 | if (f_size) |
ae512276 | 74 | (void)printf("%*qd ", |
abe0683d EA |
75 | dp->s_block, howmany(sp->st_blocks, blocksize)); |
76 | (void)strmode(sp->st_mode, buf); | |
77 | np = p->fts_pointer; | |
78 | (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, | |
79 | sp->st_nlink, dp->s_user, np->user, dp->s_group, | |
80 | np->group); | |
32980675 | 81 | if (f_flags) |
abe0683d EA |
82 | (void)printf("%-*s ", dp->s_flags, np->flags); |
83 | if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) | |
d22495b4 EA |
84 | (void)printf("%3d, %3d ", |
85 | major(sp->st_rdev), minor(sp->st_rdev)); | |
09cf81e2 KB |
86 | else if (dp->bcfile) |
87 | (void)printf("%*s%*qd ", | |
88 | 8 - dp->s_size, "", dp->s_size, sp->st_size); | |
75a967bb | 89 | else |
67d7fe00 | 90 | (void)printf("%*qd ", dp->s_size, sp->st_size); |
75a967bb | 91 | if (f_accesstime) |
d22495b4 | 92 | printtime(sp->st_atime); |
75a967bb | 93 | else if (f_statustime) |
d22495b4 | 94 | printtime(sp->st_ctime); |
75a967bb | 95 | else |
d22495b4 EA |
96 | printtime(sp->st_mtime); |
97 | (void)printf("%s", p->fts_name); | |
75a967bb | 98 | if (f_type) |
d22495b4 EA |
99 | (void)printtype(sp->st_mode); |
100 | if (S_ISLNK(sp->st_mode)) | |
101 | printlink(p); | |
75a967bb KB |
102 | (void)putchar('\n'); |
103 | } | |
104 | } | |
105 | ||
3cc8e3ba KB |
106 | #define TAB 8 |
107 | ||
0ce0ae04 | 108 | void |
abe0683d EA |
109 | printcol(dp) |
110 | DISPLAY *dp; | |
75a967bb | 111 | { |
eb8c7f67 | 112 | extern int termwidth; |
d22495b4 EA |
113 | static FTSENT **array; |
114 | static int lastentries = -1; | |
706c0358 JSP |
115 | FTSENT *p; |
116 | int base, chcnt, cnt, col, colwidth, num; | |
3cc8e3ba | 117 | int endcol, numcols, numrows, row; |
62a77e99 | 118 | |
d22495b4 EA |
119 | /* |
120 | * Have to do random access in the linked list -- build a table | |
121 | * of pointers. | |
122 | */ | |
abe0683d EA |
123 | if (dp->entries > lastentries) { |
124 | lastentries = dp->entries; | |
f565f020 | 125 | if ((array = |
abe0683d | 126 | realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { |
77c06a9f | 127 | warn(NULL); |
abe0683d | 128 | printscol(dp); |
d22495b4 EA |
129 | } |
130 | } | |
abe0683d | 131 | for (p = dp->list, num = 0; p; p = p->fts_link) |
d22495b4 EA |
132 | if (p->fts_number != NO_PRINT) |
133 | array[num++] = p; | |
134 | ||
abe0683d | 135 | colwidth = dp->maxlen; |
62a77e99 | 136 | if (f_inode) |
abe0683d | 137 | colwidth += dp->s_inode + 1; |
62a77e99 | 138 | if (f_size) |
abe0683d | 139 | colwidth += dp->s_block + 1; |
62a77e99 | 140 | if (f_type) |
9071313b | 141 | colwidth += 1; |
299cb8d5 | 142 | |
3cc8e3ba | 143 | colwidth = (colwidth + TAB) & ~(TAB - 1); |
299cb8d5 | 144 | if (termwidth < 2 * colwidth) { |
abe0683d | 145 | printscol(dp); |
299cb8d5 KB |
146 | return; |
147 | } | |
9071313b KB |
148 | |
149 | numcols = termwidth / colwidth; | |
150 | numrows = num / numcols; | |
151 | if (num % numcols) | |
152 | ++numrows; | |
62a77e99 | 153 | |
abe0683d EA |
154 | if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) |
155 | (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); | |
9071313b | 156 | for (row = 0; row < numrows; ++row) { |
67e8527c KB |
157 | endcol = colwidth; |
158 | for (base = row, chcnt = col = 0; col < numcols; ++col) { | |
abe0683d EA |
159 | chcnt += printaname(array[base], dp->s_inode, |
160 | dp->s_block); | |
9071313b | 161 | if ((base += numrows) >= num) |
62a77e99 | 162 | break; |
67e8527c | 163 | while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { |
9071313b | 164 | (void)putchar('\t'); |
67e8527c | 165 | chcnt = cnt; |
62a77e99 | 166 | } |
67e8527c | 167 | endcol += colwidth; |
62a77e99 | 168 | } |
d22495b4 | 169 | (void)putchar('\n'); |
62a77e99 KB |
170 | } |
171 | } | |
172 | ||
173 | /* | |
174 | * print [inode] [size] name | |
d22495b4 | 175 | * return # of characters printed, no trailing characters. |
62a77e99 | 176 | */ |
0ce0ae04 | 177 | static int |
abe0683d | 178 | printaname(p, inodefield, sizefield) |
706c0358 | 179 | FTSENT *p; |
abe0683d | 180 | u_long sizefield, inodefield; |
62a77e99 | 181 | { |
d22495b4 | 182 | struct stat *sp; |
75a967bb | 183 | int chcnt; |
62a77e99 | 184 | |
d22495b4 | 185 | sp = p->fts_statp; |
75a967bb | 186 | chcnt = 0; |
62a77e99 | 187 | if (f_inode) |
77c06a9f | 188 | chcnt += printf("%*lu ", (int)inodefield, sp->st_ino); |
62a77e99 | 189 | if (f_size) |
ae512276 | 190 | chcnt += printf("%*qd ", |
77c06a9f | 191 | (int)sizefield, howmany(sp->st_blocks, blocksize)); |
d22495b4 | 192 | chcnt += printf("%s", p->fts_name); |
62a77e99 | 193 | if (f_type) |
d22495b4 | 194 | chcnt += printtype(sp->st_mode); |
0ce0ae04 | 195 | return (chcnt); |
62a77e99 KB |
196 | } |
197 | ||
0ce0ae04 | 198 | static void |
62a77e99 KB |
199 | printtime(ftime) |
200 | time_t ftime; | |
201 | { | |
202 | int i; | |
0ce0ae04 | 203 | char *longstring; |
62a77e99 | 204 | |
abe0683d | 205 | longstring = ctime(&ftime); |
62a77e99 KB |
206 | for (i = 4; i < 11; ++i) |
207 | (void)putchar(longstring[i]); | |
208 | ||
209 | #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) | |
e05a6377 KB |
210 | if (f_sectime) |
211 | for (i = 11; i < 24; i++) | |
212 | (void)putchar(longstring[i]); | |
abe0683d | 213 | else if (ftime + SIXMONTHS > time(NULL)) |
62a77e99 KB |
214 | for (i = 11; i < 16; ++i) |
215 | (void)putchar(longstring[i]); | |
216 | else { | |
217 | (void)putchar(' '); | |
218 | for (i = 20; i < 24; ++i) | |
219 | (void)putchar(longstring[i]); | |
220 | } | |
221 | (void)putchar(' '); | |
222 | } | |
223 | ||
0ce0ae04 | 224 | static int |
62a77e99 | 225 | printtype(mode) |
0ce0ae04 | 226 | u_int mode; |
62a77e99 KB |
227 | { |
228 | switch(mode & S_IFMT) { | |
229 | case S_IFDIR: | |
230 | (void)putchar('/'); | |
0ce0ae04 | 231 | return (1); |
62a77e99 KB |
232 | case S_IFLNK: |
233 | (void)putchar('@'); | |
0ce0ae04 | 234 | return (1); |
62a77e99 KB |
235 | case S_IFSOCK: |
236 | (void)putchar('='); | |
0ce0ae04 | 237 | return (1); |
62a77e99 KB |
238 | } |
239 | if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { | |
240 | (void)putchar('*'); | |
0ce0ae04 | 241 | return (1); |
62a77e99 | 242 | } |
0ce0ae04 | 243 | return (0); |
62a77e99 KB |
244 | } |
245 | ||
0ce0ae04 | 246 | static void |
d22495b4 EA |
247 | printlink(p) |
248 | FTSENT *p; | |
62a77e99 KB |
249 | { |
250 | int lnklen; | |
d22495b4 | 251 | char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; |
aa3c6d10 | 252 | |
abe0683d EA |
253 | if (p->fts_level == FTS_ROOTLEVEL) |
254 | (void)snprintf(name, sizeof(name), "%s", p->fts_name); | |
15122cf0 | 255 | else |
abe0683d | 256 | (void)snprintf(name, sizeof(name), |
e0fd8a01 KB |
257 | "%s/%s", p->fts_parent->fts_accpath, p->fts_name); |
258 | if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { | |
62a77e99 KB |
259 | (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); |
260 | return; | |
261 | } | |
262 | path[lnklen] = '\0'; | |
263 | (void)printf(" -> %s", path); | |
264 | } |