print.c revision 88668
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[] = 4250471Speter "$FreeBSD: head/bin/ls/print.c 88668 2001-12-29 10:13:43Z joe $"; 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> 5388591Sjoe#include <math.h> 5474566Sache#include <langinfo.h> 551556Srgrimes#include <pwd.h> 561556Srgrimes#include <stdio.h> 571556Srgrimes#include <stdlib.h> 581556Srgrimes#include <string.h> 591556Srgrimes#include <time.h> 601556Srgrimes#include <unistd.h> 6161294Sache#ifdef COLORLS 6261294Sache#include <ctype.h> 6361294Sache#include <termcap.h> 6461294Sache#include <signal.h> 6561294Sache#endif 661556Srgrimes 671556Srgrimes#include "ls.h" 681556Srgrimes#include "extern.h" 691556Srgrimes 701556Srgrimesstatic int printaname __P((FTSENT *, u_long, u_long)); 711556Srgrimesstatic void printlink __P((FTSENT *)); 721556Srgrimesstatic void printtime __P((time_t)); 731556Srgrimesstatic int printtype __P((u_int)); 7488591Sjoestatic void printsize __P((size_t, off_t)); 7561321Sache#ifdef COLORLS 7688594Sjoestatic void endcolor __P((int)); 7788594Sjoestatic int colortype __P((mode_t)); 7861321Sache#endif 791556Srgrimes 801556Srgrimes#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 8188591Sjoe#define UNITS_2 2 821556Srgrimes 8388591Sjoe#define KILO_SZ(n) (n) 8488591Sjoe#define MEGA_SZ(n) ((n) * (n)) 8588591Sjoe#define GIGA_SZ(n) ((n) * (n) * (n)) 8688591Sjoe#define TERA_SZ(n) ((n) * (n) * (n) * (n)) 8788591Sjoe#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n)) 8888591Sjoe 8988591Sjoe#define KILO_2_SZ (KILO_SZ(1024ULL)) 9088591Sjoe#define MEGA_2_SZ (MEGA_SZ(1024ULL)) 9188591Sjoe#define GIGA_2_SZ (GIGA_SZ(1024ULL)) 9288591Sjoe#define TERA_2_SZ (TERA_SZ(1024ULL)) 9388591Sjoe#define PETA_2_SZ (PETA_SZ(1024ULL)) 9488591Sjoe 9588602Sjoeunsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ}; 9688591Sjoe 9788602Sjoetypedef enum { 9888602Sjoe NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX 9988602Sjoe} unit_t; 10088595Sjoestatic unit_t unit_adjust __P((off_t *)); 10188591Sjoe 10288602Sjoeint unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA}; 10388591Sjoe 10461268Sjoe#ifdef COLORLS 10561178Sjoe/* Most of these are taken from <sys/stat.h> */ 10661178Sjoetypedef enum Colors { 10788602Sjoe C_DIR, /* directory */ 10888602Sjoe C_LNK, /* symbolic link */ 10988602Sjoe C_SOCK, /* socket */ 11088602Sjoe C_FIFO, /* pipe */ 11188602Sjoe C_EXEC, /* executable */ 11288602Sjoe C_BLK, /* block special */ 11388602Sjoe C_CHR, /* character special */ 11488602Sjoe C_SUID, /* setuid executable */ 11588602Sjoe C_SGID, /* setgid executable */ 11688602Sjoe C_WSDIR, /* directory writeble to others, with sticky 11788602Sjoe * bit */ 11888602Sjoe C_WDIR, /* directory writeble to others, without 11988602Sjoe * sticky bit */ 12088602Sjoe C_NUMCOLORS /* just a place-holder */ 12188586Sjoe} Colors; 12261178Sjoe 12388587Sjoeconst char *defcolors = "exfxcxdxbxegedabagacad"; 12461178Sjoe 12588583Sjoe/* colors for file types */ 12688583Sjoestatic struct { 12788586Sjoe int num[2]; 12888586Sjoe int bold; 12988583Sjoe} colors[C_NUMCOLORS]; 13061268Sjoe#endif 13161178Sjoe 1321556Srgrimesvoid 1331556Srgrimesprintscol(dp) 13488594Sjoe DISPLAY *dp; 1351556Srgrimes{ 13688594Sjoe FTSENT *p; 1371556Srgrimes 1381556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1391556Srgrimes if (IS_NOPRINT(p)) 1401556Srgrimes continue; 1411556Srgrimes (void)printaname(p, dp->s_inode, dp->s_block); 1421556Srgrimes (void)putchar('\n'); 1431556Srgrimes } 1441556Srgrimes} 1451556Srgrimes 14662597Sassar/* 14762597Sassar * print name in current style 14862597Sassar */ 14962597Sassarstatic int 15062597Sassarprintname(name) 15162597Sassar const char *name; 15262597Sassar{ 15362597Sassar if (f_octal || f_octal_escape) 15462597Sassar return prn_octal(name); 15562597Sassar else if (f_nonprint) 15662597Sassar return prn_printable(name); 15762597Sassar else 15862597Sassar return printf("%s", name); 15962597Sassar} 16062597Sassar 1611556Srgrimesvoid 1621556Srgrimesprintlong(dp) 1631556Srgrimes DISPLAY *dp; 1641556Srgrimes{ 1651556Srgrimes struct stat *sp; 16688594Sjoe FTSENT *p; 16788594Sjoe NAMES *np; 16888594Sjoe char buf[20]; 16961292Sache#ifdef COLORLS 17088594Sjoe int color_printed = 0; 17161292Sache#endif 1721556Srgrimes 1731556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1741556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1751556Srgrimes 1761556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1771556Srgrimes if (IS_NOPRINT(p)) 1781556Srgrimes continue; 1791556Srgrimes sp = p->fts_statp; 1801556Srgrimes if (f_inode) 18120417Ssteve (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 1821556Srgrimes if (f_size) 1831556Srgrimes (void)printf("%*qd ", 1841556Srgrimes dp->s_block, howmany(sp->st_blocks, blocksize)); 1851556Srgrimes (void)strmode(sp->st_mode, buf); 1861556Srgrimes np = p->fts_pointer; 1871556Srgrimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1881556Srgrimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1891556Srgrimes np->group); 1901556Srgrimes if (f_flags) 1911556Srgrimes (void)printf("%-*s ", dp->s_flags, np->flags); 19286922Sgreen if (f_lomac) 19386922Sgreen (void)printf("%-*s ", dp->s_lattr, np->lattr); 1941556Srgrimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 19555514Sbde if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 19613120Sjoerg (void)printf("%3d, 0x%08x ", 19755514Sbde major(sp->st_rdev), 19855514Sbde (u_int)minor(sp->st_rdev)); 19913120Sjoerg else 20013120Sjoerg (void)printf("%3d, %3d ", 20113120Sjoerg major(sp->st_rdev), minor(sp->st_rdev)); 2021556Srgrimes else if (dp->bcfile) 2031556Srgrimes (void)printf("%*s%*qd ", 2041556Srgrimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 2051556Srgrimes else 20688591Sjoe printsize(dp->s_size, sp->st_size); 2071556Srgrimes if (f_accesstime) 2081556Srgrimes printtime(sp->st_atime); 2091556Srgrimes else if (f_statustime) 2101556Srgrimes printtime(sp->st_ctime); 2111556Srgrimes else 2121556Srgrimes printtime(sp->st_mtime); 21361268Sjoe#ifdef COLORLS 21461178Sjoe if (f_color) 21561291Sache color_printed = colortype(sp->st_mode); 21661268Sjoe#endif 21762597Sassar (void)printname(p->fts_name); 21861268Sjoe#ifdef COLORLS 21961291Sache if (f_color && color_printed) 22061321Sache endcolor(0); 22161268Sjoe#endif 2221556Srgrimes if (f_type) 2231556Srgrimes (void)printtype(sp->st_mode); 2241556Srgrimes if (S_ISLNK(sp->st_mode)) 2251556Srgrimes printlink(p); 2261556Srgrimes (void)putchar('\n'); 2271556Srgrimes } 2281556Srgrimes} 2291556Srgrimes 2301556Srgrimesvoid 2311556Srgrimesprintcol(dp) 23288594Sjoe DISPLAY *dp; 2331556Srgrimes{ 2341556Srgrimes extern int termwidth; 2351556Srgrimes static FTSENT **array; 2361556Srgrimes static int lastentries = -1; 23788594Sjoe FTSENT *p; 23888594Sjoe int base; 23988594Sjoe int chcnt; 24088594Sjoe int cnt; 24188594Sjoe int col; 24288594Sjoe int colwidth; 24388594Sjoe int endcol; 24488594Sjoe int num; 24588594Sjoe int numcols; 24688594Sjoe int numrows; 24788594Sjoe int row; 24888594Sjoe int tabwidth; 2491556Srgrimes 25037932Shoek if (f_notabs) 25137932Shoek tabwidth = 1; 25237932Shoek else 25337932Shoek tabwidth = 8; 25437932Shoek 2551556Srgrimes /* 2561556Srgrimes * Have to do random access in the linked list -- build a table 2571556Srgrimes * of pointers. 2581556Srgrimes */ 2591556Srgrimes if (dp->entries > lastentries) { 2601556Srgrimes lastentries = dp->entries; 2611556Srgrimes if ((array = 2621556Srgrimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 2631556Srgrimes warn(NULL); 2641556Srgrimes printscol(dp); 2651556Srgrimes } 2661556Srgrimes } 2671556Srgrimes for (p = dp->list, num = 0; p; p = p->fts_link) 2681556Srgrimes if (p->fts_number != NO_PRINT) 2691556Srgrimes array[num++] = p; 2701556Srgrimes 2711556Srgrimes colwidth = dp->maxlen; 2721556Srgrimes if (f_inode) 2731556Srgrimes colwidth += dp->s_inode + 1; 2741556Srgrimes if (f_size) 2751556Srgrimes colwidth += dp->s_block + 1; 2761556Srgrimes if (f_type) 2771556Srgrimes colwidth += 1; 2781556Srgrimes 27937932Shoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 2801556Srgrimes if (termwidth < 2 * colwidth) { 2811556Srgrimes printscol(dp); 2821556Srgrimes return; 2831556Srgrimes } 2841556Srgrimes numcols = termwidth / colwidth; 2851556Srgrimes numrows = num / numcols; 2861556Srgrimes if (num % numcols) 2871556Srgrimes ++numrows; 2881556Srgrimes 2891556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 2901556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 2911556Srgrimes for (row = 0; row < numrows; ++row) { 2921556Srgrimes endcol = colwidth; 2931556Srgrimes for (base = row, chcnt = col = 0; col < numcols; ++col) { 2941556Srgrimes chcnt += printaname(array[base], dp->s_inode, 2951556Srgrimes dp->s_block); 2961556Srgrimes if ((base += numrows) >= num) 2971556Srgrimes break; 29837932Shoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 29988595Sjoe <= endcol) { 30037932Shoek (void)putchar(f_notabs ? ' ' : '\t'); 3011556Srgrimes chcnt = cnt; 3021556Srgrimes } 3031556Srgrimes endcol += colwidth; 3041556Srgrimes } 3051556Srgrimes (void)putchar('\n'); 3061556Srgrimes } 3071556Srgrimes} 3081556Srgrimes 3091556Srgrimes/* 3101556Srgrimes * print [inode] [size] name 3111556Srgrimes * return # of characters printed, no trailing characters. 3121556Srgrimes */ 3131556Srgrimesstatic int 3141556Srgrimesprintaname(p, inodefield, sizefield) 31588594Sjoe FTSENT *p; 31688594Sjoe u_long inodefield; 31788594Sjoe u_long sizefield; 3181556Srgrimes{ 3191556Srgrimes struct stat *sp; 32088594Sjoe int chcnt; 32161292Sache#ifdef COLORLS 32288594Sjoe int color_printed = 0; 32361292Sache#endif 3241556Srgrimes 3251556Srgrimes sp = p->fts_statp; 3261556Srgrimes chcnt = 0; 3271556Srgrimes if (f_inode) 32820417Ssteve chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 3291556Srgrimes if (f_size) 3301556Srgrimes chcnt += printf("%*qd ", 3311556Srgrimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 33261268Sjoe#ifdef COLORLS 33361178Sjoe if (f_color) 33461291Sache color_printed = colortype(sp->st_mode); 33561268Sjoe#endif 33662597Sassar chcnt += printname(p->fts_name); 33761268Sjoe#ifdef COLORLS 33861291Sache if (f_color && color_printed) 33961321Sache endcolor(0); 34061268Sjoe#endif 3411556Srgrimes if (f_type) 3421556Srgrimes chcnt += printtype(sp->st_mode); 3431556Srgrimes return (chcnt); 3441556Srgrimes} 3451556Srgrimes 3461556Srgrimesstatic void 3471556Srgrimesprinttime(ftime) 34888594Sjoe time_t ftime; 3491556Srgrimes{ 35088594Sjoe char longstring[80]; 35188594Sjoe static time_t now; 35288594Sjoe const char *format; 35388594Sjoe static int d_first = -1; 3541556Srgrimes 35574566Sache if (d_first < 0) 35674566Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 35721545Smpp if (now == 0) 35821545Smpp now = time(NULL); 35921545Smpp 3609987Swollman#define SIXMONTHS ((365 / 2) * 86400) 3611556Srgrimes if (f_sectime) 36261920Sjoe /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 36374566Sache format = d_first ? "%e %b %T %Y " : "%b %e %T %Y "; 36421545Smpp else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 36561920Sjoe /* mmm dd hh:mm || dd mmm hh:mm */ 36674566Sache format = d_first ? "%e %b %R " : "%b %e %R "; 36761814Sjoe else 36861920Sjoe /* mmm dd yyyy || dd mmm yyyy */ 36974566Sache format = d_first ? "%e %b %Y " : "%b %e %Y "; 37061814Sjoe strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 37161814Sjoe fputs(longstring, stdout); 3721556Srgrimes} 3731556Srgrimes 3741556Srgrimesstatic int 3751556Srgrimesprinttype(mode) 37688594Sjoe u_int mode; 3771556Srgrimes{ 3781556Srgrimes switch (mode & S_IFMT) { 3791556Srgrimes case S_IFDIR: 3801556Srgrimes (void)putchar('/'); 3811556Srgrimes return (1); 3821556Srgrimes case S_IFIFO: 3831556Srgrimes (void)putchar('|'); 3841556Srgrimes return (1); 3851556Srgrimes case S_IFLNK: 3861556Srgrimes (void)putchar('@'); 3871556Srgrimes return (1); 3881556Srgrimes case S_IFSOCK: 3891556Srgrimes (void)putchar('='); 3901556Srgrimes return (1); 39120417Ssteve case S_IFWHT: 39220417Ssteve (void)putchar('%'); 39320417Ssteve return (1); 3941556Srgrimes } 3951556Srgrimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 3961556Srgrimes (void)putchar('*'); 3971556Srgrimes return (1); 3981556Srgrimes } 3991556Srgrimes return (0); 4001556Srgrimes} 4011556Srgrimes 40261268Sjoe#ifdef COLORLS 40361323Sachestatic int 40461323Sacheputch(c) 40588594Sjoe int c; 40661291Sache{ 40788602Sjoe (void)putchar(c); 40861321Sache return 0; 40961291Sache} 41061291Sache 41161323Sachestatic int 41261323Sachewritech(c) 41388594Sjoe int c; 41461321Sache{ 41588594Sjoe char tmp = c; 41661291Sache 41788602Sjoe (void)write(STDOUT_FILENO, &tmp, 1); 41861321Sache return 0; 41961321Sache} 42061321Sache 42161323Sachestatic void 42261178Sjoeprintcolor(c) 42388594Sjoe Colors c; 42461178Sjoe{ 42588594Sjoe char *ansiseq; 42661268Sjoe 42788583Sjoe if (colors[c].bold) 42888583Sjoe tputs(enter_bold, 1, putch); 42988583Sjoe 43088583Sjoe if (colors[c].num[0] != -1) { 43188583Sjoe ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 43261321Sache if (ansiseq) 43361291Sache tputs(ansiseq, 1, putch); 43461178Sjoe } 43588583Sjoe if (colors[c].num[1] != -1) { 43688583Sjoe ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 43761321Sache if (ansiseq) 43861291Sache tputs(ansiseq, 1, putch); 43961268Sjoe } 44061178Sjoe} 44161178Sjoe 44261321Sachestatic void 44361321Sacheendcolor(sig) 44488594Sjoe int sig; 44561268Sjoe{ 44661321Sache tputs(ansi_coloff, 1, sig ? writech : putch); 44788583Sjoe tputs(attrs_off, 1, sig ? writech : putch); 44861268Sjoe} 44961268Sjoe 45061321Sachestatic int 45161178Sjoecolortype(mode) 45288594Sjoe mode_t mode; 45361178Sjoe{ 45488602Sjoe switch (mode & S_IFMT) { 45588595Sjoe case S_IFDIR: 45661178Sjoe if (mode & S_IWOTH) 45788595Sjoe if (mode & S_ISTXT) 45888595Sjoe printcolor(C_WSDIR); 45988595Sjoe else 46088595Sjoe printcolor(C_WDIR); 46161178Sjoe else 46288595Sjoe printcolor(C_DIR); 46388602Sjoe return (1); 46488595Sjoe case S_IFLNK: 46561178Sjoe printcolor(C_LNK); 46688602Sjoe return (1); 46788595Sjoe case S_IFSOCK: 46861178Sjoe printcolor(C_SOCK); 46988602Sjoe return (1); 47088595Sjoe case S_IFIFO: 47161178Sjoe printcolor(C_FIFO); 47288602Sjoe return (1); 47388595Sjoe case S_IFBLK: 47461178Sjoe printcolor(C_BLK); 47588602Sjoe return (1); 47688595Sjoe case S_IFCHR: 47761178Sjoe printcolor(C_CHR); 47888602Sjoe return (1); 47961178Sjoe } 48061178Sjoe if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 48161178Sjoe if (mode & S_ISUID) 48288595Sjoe printcolor(C_SUID); 48361178Sjoe else if (mode & S_ISGID) 48488595Sjoe printcolor(C_SGID); 48561178Sjoe else 48688595Sjoe printcolor(C_EXEC); 48788602Sjoe return (1); 48861178Sjoe } 48988602Sjoe return (0); 49061178Sjoe} 49161178Sjoe 49261178Sjoevoid 49361178Sjoeparsecolors(cs) 49488587Sjoe const char *cs; 49561178Sjoe{ 49688594Sjoe int i; 49788594Sjoe int j; 49888594Sjoe int len; 49988594Sjoe char c[2]; 50088594Sjoe short legacy_warn = 0; 50161321Sache 50288586Sjoe if (cs == NULL) 50388602Sjoe cs = ""; /* LSCOLORS not set */ 50461178Sjoe len = strlen(cs); 50588602Sjoe for (i = 0; i < C_NUMCOLORS; i++) { 50688583Sjoe colors[i].bold = 0; 50788583Sjoe 50888586Sjoe if (len <= 2 * i) { 50988586Sjoe c[0] = defcolors[2 * i]; 51088586Sjoe c[1] = defcolors[2 * i + 1]; 51188602Sjoe } else { 51288586Sjoe c[0] = cs[2 * i]; 51388586Sjoe c[1] = cs[2 * i + 1]; 51461178Sjoe } 51588602Sjoe for (j = 0; j < 2; j++) { 51688583Sjoe /* Legacy colours used 0-7 */ 51788583Sjoe if (c[j] >= '0' && c[j] <= '7') { 51888583Sjoe colors[i].num[j] = c[j] - '0'; 51988583Sjoe if (!legacy_warn) { 52088583Sjoe fprintf(stderr, 52188668Sjoe "warn: LSCOLORS should use " 52288588Sjoe "characters a-h instead of 0-9 (" 52388588Sjoe "see the manual page)\n"); 52488583Sjoe } 52588583Sjoe legacy_warn = 1; 52688583Sjoe } else if (c[j] >= 'a' && c[j] <= 'h') 52788583Sjoe colors[i].num[j] = c[j] - 'a'; 52888583Sjoe else if (c[j] >= 'A' && c[j] <= 'H') { 52988583Sjoe colors[i].num[j] = c[j] - 'A'; 53088583Sjoe colors[i].bold = 1; 53188583Sjoe } else if (tolower((unsigned char)c[j] == 'x')) 53288583Sjoe colors[i].num[j] = -1; 53388583Sjoe else { 53461178Sjoe fprintf(stderr, 53588583Sjoe "error: invalid character '%c' in LSCOLORS" 53688583Sjoe " env var\n", c[j]); 53788584Sjoe colors[i].num[j] = -1; 53861178Sjoe } 53961178Sjoe } 54061178Sjoe } 54161178Sjoe} 54261291Sache 54361323Sachevoid 54461323Sachecolorquit(sig) 54588594Sjoe int sig; 54661291Sache{ 54761321Sache endcolor(sig); 54861294Sache 54988602Sjoe (void)signal(sig, SIG_DFL); 55088602Sjoe (void)kill(getpid(), sig); 55161291Sache} 55288602Sjoe 55388602Sjoe#endif /* COLORLS */ 55488602Sjoe 5551556Srgrimesstatic void 5561556Srgrimesprintlink(p) 55788594Sjoe FTSENT *p; 5581556Srgrimes{ 55988594Sjoe int lnklen; 56088594Sjoe char name[MAXPATHLEN + 1]; 56188594Sjoe char path[MAXPATHLEN + 1]; 5621556Srgrimes 5631556Srgrimes if (p->fts_level == FTS_ROOTLEVEL) 5641556Srgrimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 5658855Srgrimes else 5661556Srgrimes (void)snprintf(name, sizeof(name), 5671556Srgrimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 5681556Srgrimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 5691556Srgrimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 5701556Srgrimes return; 5711556Srgrimes } 5721556Srgrimes path[lnklen] = '\0'; 57362597Sassar (void)printf(" -> "); 57462597Sassar printname(path); 5751556Srgrimes} 57688591Sjoe 57788591Sjoestatic void 57888591Sjoeprintsize(width, bytes) 57988591Sjoe size_t width; 58088591Sjoe off_t bytes; 58188591Sjoe{ 58288591Sjoe unit_t unit; 58388602Sjoe 58488591Sjoe if (f_humanval) { 58588591Sjoe unit = unit_adjust(&bytes); 58688591Sjoe 58788591Sjoe if (bytes == 0) 58888591Sjoe (void)printf("%*s ", width, "0B"); 58988591Sjoe else 59088602Sjoe (void)printf("%*qd%c ", width - 1, bytes, 59188602Sjoe "BKMGTPE"[unit]); 59288602Sjoe } else 59388591Sjoe (void)printf("%*qd ", width, bytes); 59488591Sjoe} 59588591Sjoe 59688591Sjoe/* 59788591Sjoe * Output in "human-readable" format. Uses 3 digits max and puts 59888591Sjoe * unit suffixes at the end. Makes output compact and easy to read, 59988591Sjoe * especially on huge disks. 60088591Sjoe * 60188591Sjoe */ 60288591Sjoeunit_t 60388591Sjoeunit_adjust(val) 60488595Sjoe off_t *val; 60588591Sjoe{ 60688595Sjoe double abval; 60788595Sjoe unit_t unit; 60888595Sjoe unsigned int unit_sz; 60988591Sjoe 61088595Sjoe abval = fabs(*val); 61188591Sjoe 61288595Sjoe unit_sz = abval ? ilogb(abval) / 10 : 0; 61388591Sjoe 61488595Sjoe if (unit_sz >= UNIT_MAX) { 61588595Sjoe unit = NONE; 61688595Sjoe } else { 61788595Sjoe unit = unitp[unit_sz]; 61888595Sjoe *val /= (double)vals_base2[unit_sz]; 61988595Sjoe } 62088591Sjoe 62188595Sjoe return (unit); 62288591Sjoe} 623