print.c revision 27967
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1989, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Michael Fischbein. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 351556Srgrimes */ 361556Srgrimes 371556Srgrimes#ifndef lint 3827967Ssteve#if 0 3927967Sstevestatic char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 4027967Ssteve#else 4127958Sstevestatic const char rcsid[] = 4227967Ssteve "$Id: print.c,v 1.13 1997/08/07 15:33:48 steve Exp $"; 4327967Ssteve#endif 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/param.h> 471556Srgrimes#include <sys/stat.h> 481556Srgrimes 491556Srgrimes#include <err.h> 501556Srgrimes#include <errno.h> 511556Srgrimes#include <fts.h> 521556Srgrimes#include <grp.h> 531556Srgrimes#include <pwd.h> 541556Srgrimes#include <stdio.h> 551556Srgrimes#include <stdlib.h> 561556Srgrimes#include <string.h> 571556Srgrimes#include <time.h> 581556Srgrimes#include <unistd.h> 591556Srgrimes 601556Srgrimes#include "ls.h" 611556Srgrimes#include "extern.h" 621556Srgrimes 631556Srgrimesstatic int printaname __P((FTSENT *, u_long, u_long)); 641556Srgrimesstatic void printlink __P((FTSENT *)); 651556Srgrimesstatic void printtime __P((time_t)); 661556Srgrimesstatic int printtype __P((u_int)); 671556Srgrimes 681556Srgrimes#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 691556Srgrimes 701556Srgrimesvoid 711556Srgrimesprintscol(dp) 721556Srgrimes DISPLAY *dp; 731556Srgrimes{ 741556Srgrimes FTSENT *p; 751556Srgrimes 761556Srgrimes for (p = dp->list; p; p = p->fts_link) { 771556Srgrimes if (IS_NOPRINT(p)) 781556Srgrimes continue; 791556Srgrimes (void)printaname(p, dp->s_inode, dp->s_block); 801556Srgrimes (void)putchar('\n'); 811556Srgrimes } 821556Srgrimes} 831556Srgrimes 841556Srgrimesvoid 851556Srgrimesprintlong(dp) 861556Srgrimes DISPLAY *dp; 871556Srgrimes{ 881556Srgrimes struct stat *sp; 891556Srgrimes FTSENT *p; 901556Srgrimes NAMES *np; 911556Srgrimes char buf[20]; 921556Srgrimes 931556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 941556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 951556Srgrimes 961556Srgrimes for (p = dp->list; p; p = p->fts_link) { 971556Srgrimes if (IS_NOPRINT(p)) 981556Srgrimes continue; 991556Srgrimes sp = p->fts_statp; 1001556Srgrimes if (f_inode) 10120417Ssteve (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 1021556Srgrimes if (f_size) 1031556Srgrimes (void)printf("%*qd ", 1041556Srgrimes dp->s_block, howmany(sp->st_blocks, blocksize)); 1051556Srgrimes (void)strmode(sp->st_mode, buf); 1061556Srgrimes np = p->fts_pointer; 1071556Srgrimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1081556Srgrimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1091556Srgrimes np->group); 1101556Srgrimes if (f_flags) 1111556Srgrimes (void)printf("%-*s ", dp->s_flags, np->flags); 1121556Srgrimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 11313120Sjoerg if (minor(sp->st_rdev) > 255) 11413120Sjoerg (void)printf("%3d, 0x%08x ", 11513120Sjoerg major(sp->st_rdev), minor(sp->st_rdev)); 11613120Sjoerg else 11713120Sjoerg (void)printf("%3d, %3d ", 11813120Sjoerg major(sp->st_rdev), minor(sp->st_rdev)); 1191556Srgrimes else if (dp->bcfile) 1201556Srgrimes (void)printf("%*s%*qd ", 1211556Srgrimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 1221556Srgrimes else 1231556Srgrimes (void)printf("%*qd ", dp->s_size, sp->st_size); 1241556Srgrimes if (f_accesstime) 1251556Srgrimes printtime(sp->st_atime); 1261556Srgrimes else if (f_statustime) 1271556Srgrimes printtime(sp->st_ctime); 1281556Srgrimes else 1291556Srgrimes printtime(sp->st_mtime); 1301556Srgrimes (void)printf("%s", p->fts_name); 1311556Srgrimes if (f_type) 1321556Srgrimes (void)printtype(sp->st_mode); 1331556Srgrimes if (S_ISLNK(sp->st_mode)) 1341556Srgrimes printlink(p); 1351556Srgrimes (void)putchar('\n'); 1361556Srgrimes } 1371556Srgrimes} 1381556Srgrimes 1391556Srgrimes#define TAB 8 1401556Srgrimes 1411556Srgrimesvoid 1421556Srgrimesprintcol(dp) 1431556Srgrimes DISPLAY *dp; 1441556Srgrimes{ 1451556Srgrimes extern int termwidth; 1461556Srgrimes static FTSENT **array; 1471556Srgrimes static int lastentries = -1; 1481556Srgrimes FTSENT *p; 1491556Srgrimes int base, chcnt, cnt, col, colwidth, num; 1501556Srgrimes int endcol, numcols, numrows, row; 1511556Srgrimes 1521556Srgrimes /* 1531556Srgrimes * Have to do random access in the linked list -- build a table 1541556Srgrimes * of pointers. 1551556Srgrimes */ 1561556Srgrimes if (dp->entries > lastentries) { 1571556Srgrimes lastentries = dp->entries; 1581556Srgrimes if ((array = 1591556Srgrimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 1601556Srgrimes warn(NULL); 1611556Srgrimes printscol(dp); 1621556Srgrimes } 1631556Srgrimes } 1641556Srgrimes for (p = dp->list, num = 0; p; p = p->fts_link) 1651556Srgrimes if (p->fts_number != NO_PRINT) 1661556Srgrimes array[num++] = p; 1671556Srgrimes 1681556Srgrimes colwidth = dp->maxlen; 1691556Srgrimes if (f_inode) 1701556Srgrimes colwidth += dp->s_inode + 1; 1711556Srgrimes if (f_size) 1721556Srgrimes colwidth += dp->s_block + 1; 1731556Srgrimes if (f_type) 1741556Srgrimes colwidth += 1; 1751556Srgrimes 1761556Srgrimes colwidth = (colwidth + TAB) & ~(TAB - 1); 1771556Srgrimes if (termwidth < 2 * colwidth) { 1781556Srgrimes printscol(dp); 1791556Srgrimes return; 1801556Srgrimes } 1811556Srgrimes 1821556Srgrimes numcols = termwidth / colwidth; 1831556Srgrimes numrows = num / numcols; 1841556Srgrimes if (num % numcols) 1851556Srgrimes ++numrows; 1861556Srgrimes 1871556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1881556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1891556Srgrimes for (row = 0; row < numrows; ++row) { 1901556Srgrimes endcol = colwidth; 1911556Srgrimes for (base = row, chcnt = col = 0; col < numcols; ++col) { 1921556Srgrimes chcnt += printaname(array[base], dp->s_inode, 1931556Srgrimes dp->s_block); 1941556Srgrimes if ((base += numrows) >= num) 1951556Srgrimes break; 1967165Sjoerg while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol){ 1971556Srgrimes (void)putchar('\t'); 1981556Srgrimes chcnt = cnt; 1991556Srgrimes } 2001556Srgrimes endcol += colwidth; 2011556Srgrimes } 2021556Srgrimes (void)putchar('\n'); 2031556Srgrimes } 2041556Srgrimes} 2051556Srgrimes 2061556Srgrimes/* 2071556Srgrimes * print [inode] [size] name 2081556Srgrimes * return # of characters printed, no trailing characters. 2091556Srgrimes */ 2101556Srgrimesstatic int 2111556Srgrimesprintaname(p, inodefield, sizefield) 2121556Srgrimes FTSENT *p; 2131556Srgrimes u_long sizefield, inodefield; 2141556Srgrimes{ 2151556Srgrimes struct stat *sp; 2161556Srgrimes int chcnt; 2171556Srgrimes 2181556Srgrimes sp = p->fts_statp; 2191556Srgrimes chcnt = 0; 2201556Srgrimes if (f_inode) 22120417Ssteve chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 2221556Srgrimes if (f_size) 2231556Srgrimes chcnt += printf("%*qd ", 2241556Srgrimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 2251556Srgrimes chcnt += printf("%s", p->fts_name); 2261556Srgrimes if (f_type) 2271556Srgrimes chcnt += printtype(sp->st_mode); 2281556Srgrimes return (chcnt); 2291556Srgrimes} 2301556Srgrimes 2311556Srgrimesstatic void 2321556Srgrimesprinttime(ftime) 2331556Srgrimes time_t ftime; 2341556Srgrimes{ 2351556Srgrimes int i; 2369991Sache char longstring[80]; 23721545Smpp static time_t now; 2381556Srgrimes 23921545Smpp if (now == 0) 24021545Smpp now = time(NULL); 24121545Smpp 2429991Sache strftime(longstring, sizeof(longstring), "%c", localtime(&ftime)); 2431556Srgrimes for (i = 4; i < 11; ++i) 2441556Srgrimes (void)putchar(longstring[i]); 2451556Srgrimes 2469987Swollman#define SIXMONTHS ((365 / 2) * 86400) 2471556Srgrimes if (f_sectime) 2481556Srgrimes for (i = 11; i < 24; i++) 2491556Srgrimes (void)putchar(longstring[i]); 25021545Smpp else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 2511556Srgrimes for (i = 11; i < 16; ++i) 2521556Srgrimes (void)putchar(longstring[i]); 2531556Srgrimes else { 2541556Srgrimes (void)putchar(' '); 2551556Srgrimes for (i = 20; i < 24; ++i) 2561556Srgrimes (void)putchar(longstring[i]); 2571556Srgrimes } 2581556Srgrimes (void)putchar(' '); 2591556Srgrimes} 2601556Srgrimes 2611556Srgrimesstatic int 2621556Srgrimesprinttype(mode) 2631556Srgrimes u_int mode; 2641556Srgrimes{ 2651556Srgrimes switch (mode & S_IFMT) { 2661556Srgrimes case S_IFDIR: 2671556Srgrimes (void)putchar('/'); 2681556Srgrimes return (1); 2691556Srgrimes case S_IFIFO: 2701556Srgrimes (void)putchar('|'); 2711556Srgrimes return (1); 2721556Srgrimes case S_IFLNK: 2731556Srgrimes (void)putchar('@'); 2741556Srgrimes return (1); 2751556Srgrimes case S_IFSOCK: 2761556Srgrimes (void)putchar('='); 2771556Srgrimes return (1); 27820417Ssteve case S_IFWHT: 27920417Ssteve (void)putchar('%'); 28020417Ssteve return (1); 2811556Srgrimes } 2821556Srgrimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 2831556Srgrimes (void)putchar('*'); 2841556Srgrimes return (1); 2851556Srgrimes } 2861556Srgrimes return (0); 2871556Srgrimes} 2881556Srgrimes 2891556Srgrimesstatic void 2901556Srgrimesprintlink(p) 2911556Srgrimes FTSENT *p; 2921556Srgrimes{ 2931556Srgrimes int lnklen; 2941556Srgrimes char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; 2951556Srgrimes 2961556Srgrimes if (p->fts_level == FTS_ROOTLEVEL) 2971556Srgrimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 2988855Srgrimes else 2991556Srgrimes (void)snprintf(name, sizeof(name), 3001556Srgrimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 3011556Srgrimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 3021556Srgrimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 3031556Srgrimes return; 3041556Srgrimes } 3051556Srgrimes path[lnklen] = '\0'; 3061556Srgrimes (void)printf(" -> %s", path); 3071556Srgrimes} 308