print.c revision 88595
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 88595 2001-12-28 21:55:23Z 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 9588595Sjoeunsigned long long vals_base2[] = { 1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ }; 9688591Sjoe 9788591Sjoetypedef enum { NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX } unit_t; 9888595Sjoestatic unit_t unit_adjust __P((off_t *)); 9988591Sjoe 10088591Sjoeint unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA }; 10188591Sjoe 10261268Sjoe#ifdef COLORLS 10361178Sjoe/* Most of these are taken from <sys/stat.h> */ 10461178Sjoetypedef enum Colors { 10588586Sjoe C_DIR, /* directory */ 10688586Sjoe C_LNK, /* symbolic link */ 10788586Sjoe C_SOCK, /* socket */ 10888586Sjoe C_FIFO, /* pipe */ 10988586Sjoe C_EXEC, /* executable */ 11088586Sjoe C_BLK, /* block special */ 11188586Sjoe C_CHR, /* character special */ 11288586Sjoe C_SUID, /* setuid executable */ 11388586Sjoe C_SGID, /* setgid executable */ 11488586Sjoe C_WSDIR, /* directory writeble to others, with sticky bit */ 11588586Sjoe C_WDIR, /* directory writeble to others, without sticky bit */ 11688586Sjoe C_NUMCOLORS /* just a place-holder */ 11788586Sjoe} Colors; 11861178Sjoe 11988587Sjoeconst char *defcolors = "exfxcxdxbxegedabagacad"; 12061178Sjoe 12188583Sjoe/* colors for file types */ 12288583Sjoestatic struct { 12388586Sjoe int num[2]; 12488586Sjoe int bold; 12588583Sjoe} colors[C_NUMCOLORS]; 12688583Sjoe 12761268Sjoe#endif 12861178Sjoe 1291556Srgrimesvoid 1301556Srgrimesprintscol(dp) 13188594Sjoe DISPLAY *dp; 1321556Srgrimes{ 13388594Sjoe FTSENT *p; 1341556Srgrimes 1351556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1361556Srgrimes if (IS_NOPRINT(p)) 1371556Srgrimes continue; 1381556Srgrimes (void)printaname(p, dp->s_inode, dp->s_block); 1391556Srgrimes (void)putchar('\n'); 1401556Srgrimes } 1411556Srgrimes} 1421556Srgrimes 14362597Sassar/* 14462597Sassar * print name in current style 14562597Sassar */ 14662597Sassarstatic int 14762597Sassarprintname(name) 14862597Sassar const char *name; 14962597Sassar{ 15062597Sassar if (f_octal || f_octal_escape) 15162597Sassar return prn_octal(name); 15262597Sassar else if (f_nonprint) 15362597Sassar return prn_printable(name); 15462597Sassar else 15562597Sassar return printf("%s", name); 15662597Sassar} 15762597Sassar 1581556Srgrimesvoid 1591556Srgrimesprintlong(dp) 1601556Srgrimes DISPLAY *dp; 1611556Srgrimes{ 1621556Srgrimes struct stat *sp; 16388594Sjoe FTSENT *p; 16488594Sjoe NAMES *np; 16588594Sjoe char buf[20]; 16661292Sache#ifdef COLORLS 16788594Sjoe int color_printed = 0; 16861292Sache#endif 1691556Srgrimes 1701556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1711556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1721556Srgrimes 1731556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1741556Srgrimes if (IS_NOPRINT(p)) 1751556Srgrimes continue; 1761556Srgrimes sp = p->fts_statp; 1771556Srgrimes if (f_inode) 17820417Ssteve (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 1791556Srgrimes if (f_size) 1801556Srgrimes (void)printf("%*qd ", 1811556Srgrimes dp->s_block, howmany(sp->st_blocks, blocksize)); 1821556Srgrimes (void)strmode(sp->st_mode, buf); 1831556Srgrimes np = p->fts_pointer; 1841556Srgrimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1851556Srgrimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1861556Srgrimes np->group); 1871556Srgrimes if (f_flags) 1881556Srgrimes (void)printf("%-*s ", dp->s_flags, np->flags); 18986922Sgreen if (f_lomac) 19086922Sgreen (void)printf("%-*s ", dp->s_lattr, np->lattr); 1911556Srgrimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 19255514Sbde if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 19313120Sjoerg (void)printf("%3d, 0x%08x ", 19455514Sbde major(sp->st_rdev), 19555514Sbde (u_int)minor(sp->st_rdev)); 19613120Sjoerg else 19713120Sjoerg (void)printf("%3d, %3d ", 19813120Sjoerg major(sp->st_rdev), minor(sp->st_rdev)); 1991556Srgrimes else if (dp->bcfile) 2001556Srgrimes (void)printf("%*s%*qd ", 2011556Srgrimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 2021556Srgrimes else 20388591Sjoe printsize(dp->s_size, sp->st_size); 2041556Srgrimes if (f_accesstime) 2051556Srgrimes printtime(sp->st_atime); 2061556Srgrimes else if (f_statustime) 2071556Srgrimes printtime(sp->st_ctime); 2081556Srgrimes else 2091556Srgrimes printtime(sp->st_mtime); 21061268Sjoe#ifdef COLORLS 21161178Sjoe if (f_color) 21261291Sache color_printed = colortype(sp->st_mode); 21361268Sjoe#endif 21462597Sassar (void)printname(p->fts_name); 21561268Sjoe#ifdef COLORLS 21661291Sache if (f_color && color_printed) 21761321Sache endcolor(0); 21861268Sjoe#endif 2191556Srgrimes if (f_type) 2201556Srgrimes (void)printtype(sp->st_mode); 2211556Srgrimes if (S_ISLNK(sp->st_mode)) 2221556Srgrimes printlink(p); 2231556Srgrimes (void)putchar('\n'); 2241556Srgrimes } 2251556Srgrimes} 2261556Srgrimes 2271556Srgrimesvoid 2281556Srgrimesprintcol(dp) 22988594Sjoe DISPLAY *dp; 2301556Srgrimes{ 2311556Srgrimes extern int termwidth; 2321556Srgrimes static FTSENT **array; 2331556Srgrimes static int lastentries = -1; 23488594Sjoe FTSENT *p; 23588594Sjoe int base; 23688594Sjoe int chcnt; 23788594Sjoe int cnt; 23888594Sjoe int col; 23988594Sjoe int colwidth; 24088594Sjoe int endcol; 24188594Sjoe int num; 24288594Sjoe int numcols; 24388594Sjoe int numrows; 24488594Sjoe int row; 24588594Sjoe int tabwidth; 2461556Srgrimes 24737932Shoek if (f_notabs) 24837932Shoek tabwidth = 1; 24937932Shoek else 25037932Shoek tabwidth = 8; 25137932Shoek 2521556Srgrimes /* 2531556Srgrimes * Have to do random access in the linked list -- build a table 2541556Srgrimes * of pointers. 2551556Srgrimes */ 2561556Srgrimes if (dp->entries > lastentries) { 2571556Srgrimes lastentries = dp->entries; 2581556Srgrimes if ((array = 2591556Srgrimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 2601556Srgrimes warn(NULL); 2611556Srgrimes printscol(dp); 2621556Srgrimes } 2631556Srgrimes } 2641556Srgrimes for (p = dp->list, num = 0; p; p = p->fts_link) 2651556Srgrimes if (p->fts_number != NO_PRINT) 2661556Srgrimes array[num++] = p; 2671556Srgrimes 2681556Srgrimes colwidth = dp->maxlen; 2691556Srgrimes if (f_inode) 2701556Srgrimes colwidth += dp->s_inode + 1; 2711556Srgrimes if (f_size) 2721556Srgrimes colwidth += dp->s_block + 1; 2731556Srgrimes if (f_type) 2741556Srgrimes colwidth += 1; 2751556Srgrimes 27637932Shoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 2771556Srgrimes if (termwidth < 2 * colwidth) { 2781556Srgrimes printscol(dp); 2791556Srgrimes return; 2801556Srgrimes } 2811556Srgrimes 2821556Srgrimes numcols = termwidth / colwidth; 2831556Srgrimes numrows = num / numcols; 2841556Srgrimes if (num % numcols) 2851556Srgrimes ++numrows; 2861556Srgrimes 2871556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 2881556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 2891556Srgrimes for (row = 0; row < numrows; ++row) { 2901556Srgrimes endcol = colwidth; 2911556Srgrimes for (base = row, chcnt = col = 0; col < numcols; ++col) { 2921556Srgrimes chcnt += printaname(array[base], dp->s_inode, 2931556Srgrimes dp->s_block); 2941556Srgrimes if ((base += numrows) >= num) 2951556Srgrimes break; 29637932Shoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 29788595Sjoe <= endcol) { 29837932Shoek (void)putchar(f_notabs ? ' ' : '\t'); 2991556Srgrimes chcnt = cnt; 3001556Srgrimes } 3011556Srgrimes endcol += colwidth; 3021556Srgrimes } 3031556Srgrimes (void)putchar('\n'); 3041556Srgrimes } 3051556Srgrimes} 3061556Srgrimes 3071556Srgrimes/* 3081556Srgrimes * print [inode] [size] name 3091556Srgrimes * return # of characters printed, no trailing characters. 3101556Srgrimes */ 3111556Srgrimesstatic int 3121556Srgrimesprintaname(p, inodefield, sizefield) 31388594Sjoe FTSENT *p; 31488594Sjoe u_long inodefield; 31588594Sjoe u_long sizefield; 3161556Srgrimes{ 3171556Srgrimes struct stat *sp; 31888594Sjoe int chcnt; 31961292Sache#ifdef COLORLS 32088594Sjoe int color_printed = 0; 32161292Sache#endif 3221556Srgrimes 3231556Srgrimes sp = p->fts_statp; 3241556Srgrimes chcnt = 0; 3251556Srgrimes if (f_inode) 32620417Ssteve chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 3271556Srgrimes if (f_size) 3281556Srgrimes chcnt += printf("%*qd ", 3291556Srgrimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 33061268Sjoe#ifdef COLORLS 33161178Sjoe if (f_color) 33261291Sache color_printed = colortype(sp->st_mode); 33361268Sjoe#endif 33462597Sassar chcnt += printname(p->fts_name); 33561268Sjoe#ifdef COLORLS 33661291Sache if (f_color && color_printed) 33761321Sache endcolor(0); 33861268Sjoe#endif 3391556Srgrimes if (f_type) 3401556Srgrimes chcnt += printtype(sp->st_mode); 3411556Srgrimes return (chcnt); 3421556Srgrimes} 3431556Srgrimes 3441556Srgrimesstatic void 3451556Srgrimesprinttime(ftime) 34688594Sjoe time_t ftime; 3471556Srgrimes{ 34888594Sjoe char longstring[80]; 34988594Sjoe static time_t now; 35088594Sjoe const char *format; 35188594Sjoe static int d_first = -1; 3521556Srgrimes 35374566Sache if (d_first < 0) 35474566Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 35521545Smpp if (now == 0) 35621545Smpp now = time(NULL); 35721545Smpp 3589987Swollman#define SIXMONTHS ((365 / 2) * 86400) 3591556Srgrimes if (f_sectime) 36061920Sjoe /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 36174566Sache format = d_first ? "%e %b %T %Y " : "%b %e %T %Y "; 36221545Smpp else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 36361920Sjoe /* mmm dd hh:mm || dd mmm hh:mm */ 36474566Sache format = d_first ? "%e %b %R " : "%b %e %R "; 36561814Sjoe else 36661920Sjoe /* mmm dd yyyy || dd mmm yyyy */ 36774566Sache format = d_first ? "%e %b %Y " : "%b %e %Y "; 36861814Sjoe strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 36961814Sjoe fputs(longstring, stdout); 3701556Srgrimes} 3711556Srgrimes 3721556Srgrimesstatic int 3731556Srgrimesprinttype(mode) 37488594Sjoe u_int mode; 3751556Srgrimes{ 3761556Srgrimes switch (mode & S_IFMT) { 3771556Srgrimes case S_IFDIR: 3781556Srgrimes (void)putchar('/'); 3791556Srgrimes return (1); 3801556Srgrimes case S_IFIFO: 3811556Srgrimes (void)putchar('|'); 3821556Srgrimes return (1); 3831556Srgrimes case S_IFLNK: 3841556Srgrimes (void)putchar('@'); 3851556Srgrimes return (1); 3861556Srgrimes case S_IFSOCK: 3871556Srgrimes (void)putchar('='); 3881556Srgrimes return (1); 38920417Ssteve case S_IFWHT: 39020417Ssteve (void)putchar('%'); 39120417Ssteve return (1); 3921556Srgrimes } 3931556Srgrimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 3941556Srgrimes (void)putchar('*'); 3951556Srgrimes return (1); 3961556Srgrimes } 3971556Srgrimes return (0); 3981556Srgrimes} 3991556Srgrimes 40061268Sjoe#ifdef COLORLS 40161323Sachestatic int 40261323Sacheputch(c) 40388594Sjoe int c; 40461291Sache{ 40561321Sache (void) putchar(c); 40661321Sache return 0; 40761291Sache} 40861291Sache 40961323Sachestatic int 41061323Sachewritech(c) 41188594Sjoe int c; 41261321Sache{ 41388594Sjoe char tmp = c; 41461291Sache 41561321Sache (void) write(STDOUT_FILENO, &tmp, 1); 41661321Sache return 0; 41761321Sache} 41861321Sache 41961323Sachestatic void 42061178Sjoeprintcolor(c) 42188594Sjoe Colors c; 42261178Sjoe{ 42388594Sjoe char *ansiseq; 42461268Sjoe 42588583Sjoe if (colors[c].bold) 42688583Sjoe tputs(enter_bold, 1, putch); 42788583Sjoe 42888583Sjoe if (colors[c].num[0] != -1) { 42988583Sjoe ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 43061321Sache if (ansiseq) 43161291Sache tputs(ansiseq, 1, putch); 43261178Sjoe } 43361268Sjoe 43488583Sjoe if (colors[c].num[1] != -1) { 43588583Sjoe ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 43661321Sache if (ansiseq) 43761291Sache tputs(ansiseq, 1, putch); 43861268Sjoe } 43961178Sjoe} 44061178Sjoe 44161321Sachestatic void 44261321Sacheendcolor(sig) 44388594Sjoe int sig; 44461268Sjoe{ 44561321Sache tputs(ansi_coloff, 1, sig ? writech : putch); 44688583Sjoe tputs(attrs_off, 1, sig ? writech : putch); 44761268Sjoe} 44861268Sjoe 44961321Sachestatic int 45061178Sjoecolortype(mode) 45188594Sjoe mode_t mode; 45261178Sjoe{ 45361178Sjoe switch(mode & S_IFMT) { 45488595Sjoe case S_IFDIR: 45561178Sjoe if (mode & S_IWOTH) 45688595Sjoe if (mode & S_ISTXT) 45788595Sjoe printcolor(C_WSDIR); 45888595Sjoe else 45988595Sjoe printcolor(C_WDIR); 46061178Sjoe else 46188595Sjoe printcolor(C_DIR); 46261178Sjoe return(1); 46388595Sjoe case S_IFLNK: 46461178Sjoe printcolor(C_LNK); 46561178Sjoe return(1); 46688595Sjoe case S_IFSOCK: 46761178Sjoe printcolor(C_SOCK); 46861178Sjoe return(1); 46988595Sjoe case S_IFIFO: 47061178Sjoe printcolor(C_FIFO); 47161178Sjoe return(1); 47288595Sjoe case S_IFBLK: 47361178Sjoe printcolor(C_BLK); 47461178Sjoe return(1); 47588595Sjoe case S_IFCHR: 47661178Sjoe printcolor(C_CHR); 47761178Sjoe return(1); 47861178Sjoe } 47961178Sjoe if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 48061178Sjoe if (mode & S_ISUID) 48188595Sjoe printcolor(C_SUID); 48261178Sjoe else if (mode & S_ISGID) 48388595Sjoe printcolor(C_SGID); 48461178Sjoe else 48588595Sjoe printcolor(C_EXEC); 48661178Sjoe return(1); 48761178Sjoe } 48861178Sjoe return(0); 48961178Sjoe} 49061178Sjoe 49161178Sjoevoid 49261178Sjoeparsecolors(cs) 49388587Sjoe const char *cs; 49461178Sjoe{ 49588594Sjoe int i; 49688594Sjoe int j; 49788594Sjoe int len; 49888594Sjoe char c[2]; 49988594Sjoe short legacy_warn = 0; 50061321Sache 50188586Sjoe if (cs == NULL) 50288586Sjoe cs = ""; /* LSCOLORS not set */ 50361178Sjoe len = strlen(cs); 50461178Sjoe for (i = 0 ; i < C_NUMCOLORS ; i++) { 50588583Sjoe colors[i].bold = 0; 50688583Sjoe 50788586Sjoe if (len <= 2 * i) { 50888586Sjoe c[0] = defcolors[2 * i]; 50988586Sjoe c[1] = defcolors[2 * i + 1]; 51061178Sjoe } 51161178Sjoe else { 51288586Sjoe c[0] = cs[2 * i]; 51388586Sjoe c[1] = cs[2 * i + 1]; 51461178Sjoe } 51561178Sjoe 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, 52188588Sjoe "warn: LSCOLOURS 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 54961294Sache (void) signal(sig, SIG_DFL); 55061294Sache (void) kill(getpid(), sig); 55161291Sache} 55261268Sjoe#endif /*COLORLS*/ 55361178Sjoe 5541556Srgrimesstatic void 5551556Srgrimesprintlink(p) 55688594Sjoe FTSENT *p; 5571556Srgrimes{ 55888594Sjoe int lnklen; 55988594Sjoe char name[MAXPATHLEN + 1]; 56088594Sjoe char path[MAXPATHLEN + 1]; 5611556Srgrimes 5621556Srgrimes if (p->fts_level == FTS_ROOTLEVEL) 5631556Srgrimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 5648855Srgrimes else 5651556Srgrimes (void)snprintf(name, sizeof(name), 5661556Srgrimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 5671556Srgrimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 5681556Srgrimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 5691556Srgrimes return; 5701556Srgrimes } 5711556Srgrimes path[lnklen] = '\0'; 57262597Sassar (void)printf(" -> "); 57362597Sassar printname(path); 5741556Srgrimes} 57588591Sjoe 57688591Sjoestatic void 57788591Sjoeprintsize(width, bytes) 57888591Sjoe size_t width; 57988591Sjoe off_t bytes; 58088591Sjoe{ 58188591Sjoe unit_t unit; 58288591Sjoe 58388591Sjoe if (f_humanval) { 58488591Sjoe unit = unit_adjust(&bytes); 58588591Sjoe 58688591Sjoe if (bytes == 0) 58788591Sjoe (void)printf("%*s ", width, "0B"); 58888591Sjoe else 58988591Sjoe (void)printf("%*qd%c ", width - 1, bytes, 59088591Sjoe "BKMGTPE"[unit]); 59188591Sjoe } 59288591Sjoe 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