/* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Michael Fischbein. * * %sccs.include.redist.c% */ #ifndef lint static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 06/02/93"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ls.h" #include "extern.h" static int printaname __P((FTSENT *, u_long, u_long)); static void printlink __P((FTSENT *)); static void printtime __P((time_t)); static int printtype __P((u_int)); #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) void printscol(dp) DISPLAY *dp; { register FTSENT *p; for (p = dp->list; p; p = p->fts_link) { if (IS_NOPRINT(p)) continue; (void)printaname(p, dp->s_inode, dp->s_block); (void)putchar('\n'); } } void printlong(dp) DISPLAY *dp; { register FTSENT *p; register struct stat *sp; NAMES *np; char buf[20]; if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); for (p = dp->list; p; p = p->fts_link) { if (IS_NOPRINT(p)) continue; sp = p->fts_statp; if (f_inode) (void)printf("%*lu ", dp->s_inode, sp->st_ino); if (f_size) (void)printf("%*qd ", dp->s_block, howmany(sp->st_blocks, blocksize)); (void)strmode(sp->st_mode, buf); np = p->fts_pointer; (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, sp->st_nlink, dp->s_user, np->user, dp->s_group, np->group); if (f_flags) (void)printf("%-*s ", dp->s_flags, np->flags); if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) (void)printf("%3d, %3d ", major(sp->st_rdev), minor(sp->st_rdev)); else if (dp->bcfile) (void)printf("%*s%*qd ", 8 - dp->s_size, "", dp->s_size, sp->st_size); else (void)printf("%*qd ", dp->s_size, sp->st_size); if (f_accesstime) printtime(sp->st_atime); else if (f_statustime) printtime(sp->st_ctime); else printtime(sp->st_mtime); (void)printf("%s", p->fts_name); if (f_type) (void)printtype(sp->st_mode); if (S_ISLNK(sp->st_mode)) printlink(p); (void)putchar('\n'); } } #define TAB 8 void printcol(dp) DISPLAY *dp; { extern int termwidth; static FTSENT **array; static int lastentries = -1; register FTSENT *p; register int base, chcnt, cnt, col, colwidth, num; int endcol, numcols, numrows, row; /* * Have to do random access in the linked list -- build a table * of pointers. */ if (dp->entries > lastentries) { lastentries = dp->entries; if ((array = realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { warn(NULL); printscol(dp); } } for (p = dp->list, num = 0; p; p = p->fts_link) if (p->fts_number != NO_PRINT) array[num++] = p; colwidth = dp->maxlen; if (f_inode) colwidth += dp->s_inode + 1; if (f_size) colwidth += dp->s_block + 1; if (f_type) colwidth += 1; colwidth = (colwidth + TAB) & ~(TAB - 1); if (termwidth < 2 * colwidth) { printscol(dp); return; } numcols = termwidth / colwidth; numrows = num / numcols; if (num % numcols) ++numrows; if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); for (row = 0; row < numrows; ++row) { endcol = colwidth; for (base = row, chcnt = col = 0; col < numcols; ++col) { chcnt += printaname(array[base], dp->s_inode, dp->s_block); if ((base += numrows) >= num) break; while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { (void)putchar('\t'); chcnt = cnt; } endcol += colwidth; } (void)putchar('\n'); } } /* * print [inode] [size] name * return # of characters printed, no trailing characters. */ static int printaname(p, inodefield, sizefield) register FTSENT *p; u_long sizefield, inodefield; { struct stat *sp; int chcnt; sp = p->fts_statp; chcnt = 0; if (f_inode) chcnt += printf("%*lu ", (int)inodefield, sp->st_ino); if (f_size) chcnt += printf("%*qd ", (int)sizefield, howmany(sp->st_blocks, blocksize)); chcnt += printf("%s", p->fts_name); if (f_type) chcnt += printtype(sp->st_mode); return (chcnt); } static void printtime(ftime) time_t ftime; { int i; char *longstring; longstring = ctime(&ftime); for (i = 4; i < 11; ++i) (void)putchar(longstring[i]); #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) if (f_sectime) for (i = 11; i < 24; i++) (void)putchar(longstring[i]); else if (ftime + SIXMONTHS > time(NULL)) for (i = 11; i < 16; ++i) (void)putchar(longstring[i]); else { (void)putchar(' '); for (i = 20; i < 24; ++i) (void)putchar(longstring[i]); } (void)putchar(' '); } static int printtype(mode) u_int mode; { switch(mode & S_IFMT) { case S_IFDIR: (void)putchar('/'); return (1); case S_IFLNK: (void)putchar('@'); return (1); case S_IFSOCK: (void)putchar('='); return (1); } if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { (void)putchar('*'); return (1); } return (0); } static void printlink(p) FTSENT *p; { int lnklen; char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; if (p->fts_level == FTS_ROOTLEVEL) (void)snprintf(name, sizeof(name), "%s", p->fts_name); else (void)snprintf(name, sizeof(name), "%s/%s", p->fts_parent->fts_accpath, p->fts_name); if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); return; } path[lnklen] = '\0'; (void)printf(" -> %s", path); }