14b88c807SRodney W. Grimes /* 24b88c807SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Michael Fischbein. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 164b88c807SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 174b88c807SRodney W. Grimes * must display the following acknowledgement: 184b88c807SRodney W. Grimes * This product includes software developed by the University of 194b88c807SRodney W. Grimes * California, Berkeley and its contributors. 204b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 214b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 224b88c807SRodney W. Grimes * without specific prior written permission. 234b88c807SRodney W. Grimes * 244b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344b88c807SRodney W. Grimes * SUCH DAMAGE. 3589730b29SDavid Greenman * 36fb5cb208SSteve Price * $Id: print.c,v 1.8 1996/01/20 10:31:14 mpp Exp $ 374b88c807SRodney W. Grimes */ 384b88c807SRodney W. Grimes 394b88c807SRodney W. Grimes #ifndef lint 40fb5cb208SSteve Price static char const sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 414b88c807SRodney W. Grimes #endif /* not lint */ 424b88c807SRodney W. Grimes 434b88c807SRodney W. Grimes #include <sys/param.h> 444b88c807SRodney W. Grimes #include <sys/stat.h> 454b88c807SRodney W. Grimes 464b88c807SRodney W. Grimes #include <err.h> 474b88c807SRodney W. Grimes #include <errno.h> 484b88c807SRodney W. Grimes #include <fts.h> 494b88c807SRodney W. Grimes #include <grp.h> 504b88c807SRodney W. Grimes #include <pwd.h> 514b88c807SRodney W. Grimes #include <stdio.h> 524b88c807SRodney W. Grimes #include <stdlib.h> 534b88c807SRodney W. Grimes #include <string.h> 544b88c807SRodney W. Grimes #include <time.h> 554b88c807SRodney W. Grimes #include <unistd.h> 564b88c807SRodney W. Grimes 574b88c807SRodney W. Grimes #include "ls.h" 584b88c807SRodney W. Grimes #include "extern.h" 594b88c807SRodney W. Grimes 604b88c807SRodney W. Grimes static int printaname __P((FTSENT *, u_long, u_long)); 614b88c807SRodney W. Grimes static void printlink __P((FTSENT *)); 624b88c807SRodney W. Grimes static void printtime __P((time_t)); 634b88c807SRodney W. Grimes static int printtype __P((u_int)); 644b88c807SRodney W. Grimes 654b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 664b88c807SRodney W. Grimes 674b88c807SRodney W. Grimes void 684b88c807SRodney W. Grimes printscol(dp) 694b88c807SRodney W. Grimes DISPLAY *dp; 704b88c807SRodney W. Grimes { 714b88c807SRodney W. Grimes FTSENT *p; 724b88c807SRodney W. Grimes 734b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 744b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 754b88c807SRodney W. Grimes continue; 764b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 774b88c807SRodney W. Grimes (void)putchar('\n'); 784b88c807SRodney W. Grimes } 794b88c807SRodney W. Grimes } 804b88c807SRodney W. Grimes 814b88c807SRodney W. Grimes void 824b88c807SRodney W. Grimes printlong(dp) 834b88c807SRodney W. Grimes DISPLAY *dp; 844b88c807SRodney W. Grimes { 854b88c807SRodney W. Grimes struct stat *sp; 864b88c807SRodney W. Grimes FTSENT *p; 874b88c807SRodney W. Grimes NAMES *np; 884b88c807SRodney W. Grimes char buf[20]; 894b88c807SRodney W. Grimes 904b88c807SRodney W. Grimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 914b88c807SRodney W. Grimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 924b88c807SRodney W. Grimes 934b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 944b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 954b88c807SRodney W. Grimes continue; 964b88c807SRodney W. Grimes sp = p->fts_statp; 974b88c807SRodney W. Grimes if (f_inode) 98fb5cb208SSteve Price (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 994b88c807SRodney W. Grimes if (f_size) 1004b88c807SRodney W. Grimes (void)printf("%*qd ", 1014b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 1024b88c807SRodney W. Grimes (void)strmode(sp->st_mode, buf); 1034b88c807SRodney W. Grimes np = p->fts_pointer; 1044b88c807SRodney W. Grimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1054b88c807SRodney W. Grimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1064b88c807SRodney W. Grimes np->group); 1074b88c807SRodney W. Grimes if (f_flags) 1084b88c807SRodney W. Grimes (void)printf("%-*s ", dp->s_flags, np->flags); 1094b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 110df2fbf15SJoerg Wunsch if (minor(sp->st_rdev) > 255) 111df2fbf15SJoerg Wunsch (void)printf("%3d, 0x%08x ", 112df2fbf15SJoerg Wunsch major(sp->st_rdev), minor(sp->st_rdev)); 113df2fbf15SJoerg Wunsch else 1144b88c807SRodney W. Grimes (void)printf("%3d, %3d ", 1154b88c807SRodney W. Grimes major(sp->st_rdev), minor(sp->st_rdev)); 1164b88c807SRodney W. Grimes else if (dp->bcfile) 1174b88c807SRodney W. Grimes (void)printf("%*s%*qd ", 1184b88c807SRodney W. Grimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 1194b88c807SRodney W. Grimes else 1204b88c807SRodney W. Grimes (void)printf("%*qd ", dp->s_size, sp->st_size); 1214b88c807SRodney W. Grimes if (f_accesstime) 1224b88c807SRodney W. Grimes printtime(sp->st_atime); 1234b88c807SRodney W. Grimes else if (f_statustime) 1244b88c807SRodney W. Grimes printtime(sp->st_ctime); 1254b88c807SRodney W. Grimes else 1264b88c807SRodney W. Grimes printtime(sp->st_mtime); 1274b88c807SRodney W. Grimes (void)printf("%s", p->fts_name); 1284b88c807SRodney W. Grimes if (f_type) 1294b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 1304b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 1314b88c807SRodney W. Grimes printlink(p); 1324b88c807SRodney W. Grimes (void)putchar('\n'); 1334b88c807SRodney W. Grimes } 1344b88c807SRodney W. Grimes } 1354b88c807SRodney W. Grimes 1364b88c807SRodney W. Grimes #define TAB 8 1374b88c807SRodney W. Grimes 1384b88c807SRodney W. Grimes void 1394b88c807SRodney W. Grimes printcol(dp) 1404b88c807SRodney W. Grimes DISPLAY *dp; 1414b88c807SRodney W. Grimes { 1424b88c807SRodney W. Grimes extern int termwidth; 1434b88c807SRodney W. Grimes static FTSENT **array; 1444b88c807SRodney W. Grimes static int lastentries = -1; 1454b88c807SRodney W. Grimes FTSENT *p; 1464b88c807SRodney W. Grimes int base, chcnt, cnt, col, colwidth, num; 1474b88c807SRodney W. Grimes int endcol, numcols, numrows, row; 1484b88c807SRodney W. Grimes 1494b88c807SRodney W. Grimes /* 1504b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 1514b88c807SRodney W. Grimes * of pointers. 1524b88c807SRodney W. Grimes */ 1534b88c807SRodney W. Grimes if (dp->entries > lastentries) { 1544b88c807SRodney W. Grimes lastentries = dp->entries; 1554b88c807SRodney W. Grimes if ((array = 1564b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 1574b88c807SRodney W. Grimes warn(NULL); 1584b88c807SRodney W. Grimes printscol(dp); 1594b88c807SRodney W. Grimes } 1604b88c807SRodney W. Grimes } 1614b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 1624b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 1634b88c807SRodney W. Grimes array[num++] = p; 1644b88c807SRodney W. Grimes 1654b88c807SRodney W. Grimes colwidth = dp->maxlen; 1664b88c807SRodney W. Grimes if (f_inode) 1674b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 1684b88c807SRodney W. Grimes if (f_size) 1694b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 1704b88c807SRodney W. Grimes if (f_type) 1714b88c807SRodney W. Grimes colwidth += 1; 1724b88c807SRodney W. Grimes 1734b88c807SRodney W. Grimes colwidth = (colwidth + TAB) & ~(TAB - 1); 1744b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 1754b88c807SRodney W. Grimes printscol(dp); 1764b88c807SRodney W. Grimes return; 1774b88c807SRodney W. Grimes } 1784b88c807SRodney W. Grimes 1794b88c807SRodney W. Grimes numcols = termwidth / colwidth; 1804b88c807SRodney W. Grimes numrows = num / numcols; 1814b88c807SRodney W. Grimes if (num % numcols) 1824b88c807SRodney W. Grimes ++numrows; 1834b88c807SRodney W. Grimes 1844b88c807SRodney W. Grimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1854b88c807SRodney W. Grimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1864b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 1874b88c807SRodney W. Grimes endcol = colwidth; 1884b88c807SRodney W. Grimes for (base = row, chcnt = col = 0; col < numcols; ++col) { 1894b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 1904b88c807SRodney W. Grimes dp->s_block); 1914b88c807SRodney W. Grimes if ((base += numrows) >= num) 1924b88c807SRodney W. Grimes break; 1930fd510b7SJoerg Wunsch while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol){ 1944b88c807SRodney W. Grimes (void)putchar('\t'); 1954b88c807SRodney W. Grimes chcnt = cnt; 1964b88c807SRodney W. Grimes } 1974b88c807SRodney W. Grimes endcol += colwidth; 1984b88c807SRodney W. Grimes } 1994b88c807SRodney W. Grimes (void)putchar('\n'); 2004b88c807SRodney W. Grimes } 2014b88c807SRodney W. Grimes } 2024b88c807SRodney W. Grimes 2034b88c807SRodney W. Grimes /* 2044b88c807SRodney W. Grimes * print [inode] [size] name 2054b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 2064b88c807SRodney W. Grimes */ 2074b88c807SRodney W. Grimes static int 2084b88c807SRodney W. Grimes printaname(p, inodefield, sizefield) 2094b88c807SRodney W. Grimes FTSENT *p; 2104b88c807SRodney W. Grimes u_long sizefield, inodefield; 2114b88c807SRodney W. Grimes { 2124b88c807SRodney W. Grimes struct stat *sp; 2134b88c807SRodney W. Grimes int chcnt; 2144b88c807SRodney W. Grimes 2154b88c807SRodney W. Grimes sp = p->fts_statp; 2164b88c807SRodney W. Grimes chcnt = 0; 2174b88c807SRodney W. Grimes if (f_inode) 218fb5cb208SSteve Price chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 2194b88c807SRodney W. Grimes if (f_size) 2204b88c807SRodney W. Grimes chcnt += printf("%*qd ", 2214b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 2224b88c807SRodney W. Grimes chcnt += printf("%s", p->fts_name); 2234b88c807SRodney W. Grimes if (f_type) 2244b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 2254b88c807SRodney W. Grimes return (chcnt); 2264b88c807SRodney W. Grimes } 2274b88c807SRodney W. Grimes 2284b88c807SRodney W. Grimes static void 2294b88c807SRodney W. Grimes printtime(ftime) 2304b88c807SRodney W. Grimes time_t ftime; 2314b88c807SRodney W. Grimes { 2324b88c807SRodney W. Grimes int i; 233fc4a9bafSAndrey A. Chernov char longstring[80]; 2344b88c807SRodney W. Grimes 235fc4a9bafSAndrey A. Chernov strftime(longstring, sizeof(longstring), "%c", localtime(&ftime)); 2364b88c807SRodney W. Grimes for (i = 4; i < 11; ++i) 2374b88c807SRodney W. Grimes (void)putchar(longstring[i]); 2384b88c807SRodney W. Grimes 239656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 2404b88c807SRodney W. Grimes if (f_sectime) 2414b88c807SRodney W. Grimes for (i = 11; i < 24; i++) 2424b88c807SRodney W. Grimes (void)putchar(longstring[i]); 2434b88c807SRodney W. Grimes else if (ftime + SIXMONTHS > time(NULL)) 2444b88c807SRodney W. Grimes for (i = 11; i < 16; ++i) 2454b88c807SRodney W. Grimes (void)putchar(longstring[i]); 2464b88c807SRodney W. Grimes else { 2474b88c807SRodney W. Grimes (void)putchar(' '); 2484b88c807SRodney W. Grimes for (i = 20; i < 24; ++i) 2494b88c807SRodney W. Grimes (void)putchar(longstring[i]); 2504b88c807SRodney W. Grimes } 2514b88c807SRodney W. Grimes (void)putchar(' '); 2524b88c807SRodney W. Grimes } 2534b88c807SRodney W. Grimes 2544b88c807SRodney W. Grimes static int 2554b88c807SRodney W. Grimes printtype(mode) 2564b88c807SRodney W. Grimes u_int mode; 2574b88c807SRodney W. Grimes { 2584b88c807SRodney W. Grimes switch (mode & S_IFMT) { 2594b88c807SRodney W. Grimes case S_IFDIR: 2604b88c807SRodney W. Grimes (void)putchar('/'); 2614b88c807SRodney W. Grimes return (1); 2624b88c807SRodney W. Grimes case S_IFIFO: 2634b88c807SRodney W. Grimes (void)putchar('|'); 2644b88c807SRodney W. Grimes return (1); 2654b88c807SRodney W. Grimes case S_IFLNK: 2664b88c807SRodney W. Grimes (void)putchar('@'); 2674b88c807SRodney W. Grimes return (1); 2684b88c807SRodney W. Grimes case S_IFSOCK: 2694b88c807SRodney W. Grimes (void)putchar('='); 2704b88c807SRodney W. Grimes return (1); 271fb5cb208SSteve Price #ifndef BSD4_4_LITE 272fb5cb208SSteve Price case S_IFWHT: 273fb5cb208SSteve Price (void)putchar('%'); 274fb5cb208SSteve Price return (1); 275fb5cb208SSteve Price #endif 2764b88c807SRodney W. Grimes } 2774b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 2784b88c807SRodney W. Grimes (void)putchar('*'); 2794b88c807SRodney W. Grimes return (1); 2804b88c807SRodney W. Grimes } 2814b88c807SRodney W. Grimes return (0); 2824b88c807SRodney W. Grimes } 2834b88c807SRodney W. Grimes 2844b88c807SRodney W. Grimes static void 2854b88c807SRodney W. Grimes printlink(p) 2864b88c807SRodney W. Grimes FTSENT *p; 2874b88c807SRodney W. Grimes { 2884b88c807SRodney W. Grimes int lnklen; 2894b88c807SRodney W. Grimes char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; 2904b88c807SRodney W. Grimes 2914b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 2924b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 2934b88c807SRodney W. Grimes else 2944b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 2954b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 2964b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 2974b88c807SRodney W. Grimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 2984b88c807SRodney W. Grimes return; 2994b88c807SRodney W. Grimes } 3004b88c807SRodney W. Grimes path[lnklen] = '\0'; 3014b88c807SRodney W. Grimes (void)printf(" -> %s", path); 3024b88c807SRodney W. Grimes } 303