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