prettyness police
[unix-history] / usr / src / bin / ls / print.c
CommitLineData
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 12static 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
34static int printaname __P((FTSENT *, u_long, u_long));
35static void printlink __P((FTSENT *));
36static void printtime __P((time_t));
37static int printtype __P((u_int));
38
39#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
62a77e99 40
0ce0ae04 41void
abe0683d
EA
42printscol(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 55void
abe0683d
EA
56printlong(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 108void
abe0683d
EA
109printcol(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 177static int
abe0683d 178printaname(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 198static void
62a77e99
KB
199printtime(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 224static int
62a77e99 225printtype(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 246static void
d22495b4
EA
247printlink(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}