11638ec87Sbostic /*
2f0cd4fbbSpendry * Copyright (c) 1989, 1993, 1994
3b4eb6e17Smckusick * The Regents of the University of California. All rights reserved.
41638ec87Sbostic *
51ec844e4Sbostic * This code is derived from software contributed to Berkeley by
61ec844e4Sbostic * Michael Fischbein.
71ec844e4Sbostic *
80e2304afSbostic * %sccs.include.redist.c%
91638ec87Sbostic */
101638ec87Sbostic
111638ec87Sbostic #ifndef lint
12*4ba124f7Spendry static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 07/28/94";
131638ec87Sbostic #endif /* not lint */
141638ec87Sbostic
151638ec87Sbostic #include <sys/param.h>
161638ec87Sbostic #include <sys/stat.h>
17a13bcb1cSbostic
18a13bcb1cSbostic #include <err.h>
190e2304afSbostic #include <errno.h>
20a13bcb1cSbostic #include <fts.h>
211638ec87Sbostic #include <grp.h>
221638ec87Sbostic #include <pwd.h>
230e2304afSbostic #include <stdio.h>
24a13bcb1cSbostic #include <stdlib.h>
2516de9baaSbostic #include <string.h>
26a13bcb1cSbostic #include <time.h>
27a13bcb1cSbostic #include <tzfile.h>
28a13bcb1cSbostic #include <unistd.h>
29a13bcb1cSbostic #include <utmp.h>
30a13bcb1cSbostic
311638ec87Sbostic #include "ls.h"
320e2304afSbostic #include "extern.h"
331638ec87Sbostic
3421d043d1Selan static int printaname __P((FTSENT *, u_long, u_long));
356de7ee45Selan static void printlink __P((FTSENT *));
360e2304afSbostic static void printtime __P((time_t));
370e2304afSbostic static int printtype __P((u_int));
380e2304afSbostic
3921d043d1Selan #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
406de7ee45Selan
410e2304afSbostic void
printscol(dp)4221d043d1Selan printscol(dp)
4321d043d1Selan DISPLAY *dp;
441638ec87Sbostic {
456f3a9d47Spendry FTSENT *p;
466de7ee45Selan
4721d043d1Selan for (p = dp->list; p; p = p->fts_link) {
4821d043d1Selan if (IS_NOPRINT(p))
4921d043d1Selan continue;
5021d043d1Selan (void)printaname(p, dp->s_inode, dp->s_block);
517b8eabf8Sbostic (void)putchar('\n');
527b8eabf8Sbostic }
537b8eabf8Sbostic }
547b8eabf8Sbostic
550e2304afSbostic void
printlong(dp)5621d043d1Selan printlong(dp)
5721d043d1Selan DISPLAY *dp;
587b8eabf8Sbostic {
596f3a9d47Spendry struct stat *sp;
606f3a9d47Spendry FTSENT *p;
6121d043d1Selan NAMES *np;
6221d043d1Selan char buf[20];
63bc16eedbSbostic
6421d043d1Selan if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
6521d043d1Selan (void)printf("total %lu\n", howmany(dp->btotal, blocksize));
666de7ee45Selan
6721d043d1Selan for (p = dp->list; p; p = p->fts_link) {
686de7ee45Selan if (IS_NOPRINT(p))
696de7ee45Selan continue;
706de7ee45Selan sp = p->fts_statp;
717b8eabf8Sbostic if (f_inode)
7221d043d1Selan (void)printf("%*lu ", dp->s_inode, sp->st_ino);
737b8eabf8Sbostic if (f_size)
74ba8aa5deSmckusick (void)printf("%*qd ",
7521d043d1Selan dp->s_block, howmany(sp->st_blocks, blocksize));
7621d043d1Selan (void)strmode(sp->st_mode, buf);
7721d043d1Selan np = p->fts_pointer;
7821d043d1Selan (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink,
7921d043d1Selan sp->st_nlink, dp->s_user, np->user, dp->s_group,
8021d043d1Selan np->group);
8101bc9995Smckusick if (f_flags)
8221d043d1Selan (void)printf("%-*s ", dp->s_flags, np->flags);
8321d043d1Selan if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
846de7ee45Selan (void)printf("%3d, %3d ",
856de7ee45Selan major(sp->st_rdev), minor(sp->st_rdev));
86677edeabSbostic else if (dp->bcfile)
87677edeabSbostic (void)printf("%*s%*qd ",
88677edeabSbostic 8 - dp->s_size, "", dp->s_size, sp->st_size);
897b8eabf8Sbostic else
9092aa2c7bSmckusick (void)printf("%*qd ", dp->s_size, sp->st_size);
917b8eabf8Sbostic if (f_accesstime)
926de7ee45Selan printtime(sp->st_atime);
937b8eabf8Sbostic else if (f_statustime)
946de7ee45Selan printtime(sp->st_ctime);
957b8eabf8Sbostic else
966de7ee45Selan printtime(sp->st_mtime);
976de7ee45Selan (void)printf("%s", p->fts_name);
987b8eabf8Sbostic if (f_type)
996de7ee45Selan (void)printtype(sp->st_mode);
1006de7ee45Selan if (S_ISLNK(sp->st_mode))
1016de7ee45Selan printlink(p);
1027b8eabf8Sbostic (void)putchar('\n');
1037b8eabf8Sbostic }
1047b8eabf8Sbostic }
1057b8eabf8Sbostic
106faffd191Sbostic #define TAB 8
107faffd191Sbostic
1080e2304afSbostic void
printcol(dp)10921d043d1Selan printcol(dp)
11021d043d1Selan DISPLAY *dp;
1117b8eabf8Sbostic {
1125442d5fdSbostic extern int termwidth;
1136de7ee45Selan static FTSENT **array;
1146de7ee45Selan static int lastentries = -1;
1156f3a9d47Spendry FTSENT *p;
1166f3a9d47Spendry int base, chcnt, cnt, col, colwidth, num;
117faffd191Sbostic int endcol, numcols, numrows, row;
1181638ec87Sbostic
1196de7ee45Selan /*
1206de7ee45Selan * Have to do random access in the linked list -- build a table
1216de7ee45Selan * of pointers.
1226de7ee45Selan */
12321d043d1Selan if (dp->entries > lastentries) {
12421d043d1Selan lastentries = dp->entries;
1250a11f9fcSbostic if ((array =
12621d043d1Selan realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
127a13bcb1cSbostic warn(NULL);
12821d043d1Selan printscol(dp);
1296de7ee45Selan }
1306de7ee45Selan }
13121d043d1Selan for (p = dp->list, num = 0; p; p = p->fts_link)
1326de7ee45Selan if (p->fts_number != NO_PRINT)
1336de7ee45Selan array[num++] = p;
1346de7ee45Selan
13521d043d1Selan colwidth = dp->maxlen;
1361638ec87Sbostic if (f_inode)
13721d043d1Selan colwidth += dp->s_inode + 1;
1381638ec87Sbostic if (f_size)
13921d043d1Selan colwidth += dp->s_block + 1;
1401638ec87Sbostic if (f_type)
141983624daSbostic colwidth += 1;
142249e4f75Sbostic
143faffd191Sbostic colwidth = (colwidth + TAB) & ~(TAB - 1);
144249e4f75Sbostic if (termwidth < 2 * colwidth) {
14521d043d1Selan printscol(dp);
146249e4f75Sbostic return;
147249e4f75Sbostic }
1481638ec87Sbostic
149983624daSbostic numcols = termwidth / colwidth;
150983624daSbostic numrows = num / numcols;
151983624daSbostic if (num % numcols)
152983624daSbostic ++numrows;
153983624daSbostic
15421d043d1Selan if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
15521d043d1Selan (void)printf("total %lu\n", howmany(dp->btotal, blocksize));
156983624daSbostic for (row = 0; row < numrows; ++row) {
15741342febSbostic endcol = colwidth;
15841342febSbostic for (base = row, chcnt = col = 0; col < numcols; ++col) {
15921d043d1Selan chcnt += printaname(array[base], dp->s_inode,
16021d043d1Selan dp->s_block);
161983624daSbostic if ((base += numrows) >= num)
1621638ec87Sbostic break;
16341342febSbostic while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
1641638ec87Sbostic (void)putchar('\t');
16541342febSbostic chcnt = cnt;
1661638ec87Sbostic }
16741342febSbostic endcol += colwidth;
1681638ec87Sbostic }
1696de7ee45Selan (void)putchar('\n');
1701638ec87Sbostic }
1711638ec87Sbostic }
1721638ec87Sbostic
1731638ec87Sbostic /*
1741638ec87Sbostic * print [inode] [size] name
1756de7ee45Selan * return # of characters printed, no trailing characters.
1761638ec87Sbostic */
1770e2304afSbostic static int
printaname(p,inodefield,sizefield)17821d043d1Selan printaname(p, inodefield, sizefield)
1796f3a9d47Spendry FTSENT *p;
18021d043d1Selan u_long sizefield, inodefield;
1811638ec87Sbostic {
1826de7ee45Selan struct stat *sp;
1837b8eabf8Sbostic int chcnt;
1841638ec87Sbostic
1856de7ee45Selan sp = p->fts_statp;
1867b8eabf8Sbostic chcnt = 0;
1871638ec87Sbostic if (f_inode)
188a13bcb1cSbostic chcnt += printf("%*lu ", (int)inodefield, sp->st_ino);
1891638ec87Sbostic if (f_size)
190ba8aa5deSmckusick chcnt += printf("%*qd ",
191a13bcb1cSbostic (int)sizefield, howmany(sp->st_blocks, blocksize));
1926de7ee45Selan chcnt += printf("%s", p->fts_name);
1931638ec87Sbostic if (f_type)
1946de7ee45Selan chcnt += printtype(sp->st_mode);
1951638ec87Sbostic return (chcnt);
1961638ec87Sbostic }
1971638ec87Sbostic
1980e2304afSbostic static void
printtime(ftime)1991638ec87Sbostic printtime(ftime)
2001638ec87Sbostic time_t ftime;
2011638ec87Sbostic {
2021638ec87Sbostic int i;
2030e2304afSbostic char *longstring;
2041638ec87Sbostic
20521d043d1Selan longstring = ctime(&ftime);
2061638ec87Sbostic for (i = 4; i < 11; ++i)
2071638ec87Sbostic (void)putchar(longstring[i]);
2081638ec87Sbostic
2091638ec87Sbostic #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
2107b563e9fSbostic if (f_sectime)
2117b563e9fSbostic for (i = 11; i < 24; i++)
2127b563e9fSbostic (void)putchar(longstring[i]);
21321d043d1Selan else if (ftime + SIXMONTHS > time(NULL))
2141638ec87Sbostic for (i = 11; i < 16; ++i)
2151638ec87Sbostic (void)putchar(longstring[i]);
2161638ec87Sbostic else {
2171638ec87Sbostic (void)putchar(' ');
2181638ec87Sbostic for (i = 20; i < 24; ++i)
2191638ec87Sbostic (void)putchar(longstring[i]);
2201638ec87Sbostic }
2211638ec87Sbostic (void)putchar(' ');
2221638ec87Sbostic }
2231638ec87Sbostic
2240e2304afSbostic static int
printtype(mode)2251638ec87Sbostic printtype(mode)
2260e2304afSbostic u_int mode;
2271638ec87Sbostic {
2281638ec87Sbostic switch (mode & S_IFMT) {
2291638ec87Sbostic case S_IFDIR:
2301638ec87Sbostic (void)putchar('/');
2311638ec87Sbostic return (1);
232537be046Sbostic case S_IFIFO:
233537be046Sbostic (void)putchar('|');
234537be046Sbostic return (1);
2351638ec87Sbostic case S_IFLNK:
2361638ec87Sbostic (void)putchar('@');
2371638ec87Sbostic return (1);
2381638ec87Sbostic case S_IFSOCK:
2391638ec87Sbostic (void)putchar('=');
2401638ec87Sbostic return (1);
241*4ba124f7Spendry case S_IFWHT:
242*4ba124f7Spendry (void)putchar('%');
243*4ba124f7Spendry return (1);
2441638ec87Sbostic }
2451638ec87Sbostic if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
2461638ec87Sbostic (void)putchar('*');
2471638ec87Sbostic return (1);
2481638ec87Sbostic }
2491638ec87Sbostic return (0);
2501638ec87Sbostic }
2511638ec87Sbostic
2520e2304afSbostic static void
printlink(p)2536de7ee45Selan printlink(p)
2546de7ee45Selan FTSENT *p;
2551638ec87Sbostic {
2561638ec87Sbostic int lnklen;
2576de7ee45Selan char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
2581638ec87Sbostic
25998058b8cSelan if (p->fts_level == FTS_ROOTLEVEL)
26021d043d1Selan (void)snprintf(name, sizeof(name), "%s", p->fts_name);
26198058b8cSelan else
26221d043d1Selan (void)snprintf(name, sizeof(name),
263e99f9988Sbostic "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
264e99f9988Sbostic if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
2651638ec87Sbostic (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
2661638ec87Sbostic return;
2671638ec87Sbostic }
2681638ec87Sbostic path[lnklen] = '\0';
2691638ec87Sbostic (void)printf(" -> %s", path);
2701638ec87Sbostic }
271