always print out something for -o option
[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 *
0ce0ae04 8 * %sccs.include.redist.c%
62a77e99
KB
9 */
10
11#ifndef lint
abe0683d 12static 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
31static int printaname __P((FTSENT *, u_long, u_long));
32static void printlink __P((FTSENT *));
33static void printtime __P((time_t));
34static int printtype __P((u_int));
35
36#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
62a77e99 37
0ce0ae04 38void
abe0683d
EA
39printscol(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 52void
abe0683d
EA
53printlong(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 102void
abe0683d
EA
103printcol(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 171static int
abe0683d 172printaname(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 192static void
62a77e99
KB
193printtime(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 218static int
62a77e99 219printtype(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 240static void
d22495b4
EA
241printlink(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}